Dubbo服务导出方式
Dubbo导出服务方式主要
- xml方式
- 注解方式
xml配置方式
dubbo服务xml导出方式示例:
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>
<dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService" version="1"/>
</beans>
对于dubbo来说,通过spring提供的xml扩展来解析dubbo自定义的标签,如果要自定义标签通过spring解析,主要步骤有以下几步:
- schema文件用来定义xml文件编写规范,定义有哪些标签,有什么属性
- NameSpaceHandler(命名空间处理器)—向spring中添加标签处理器
- 编写
spring.handlers
文件,用来绑定命名空间解析类(NamespaceHandlerSupport) - 编写
spring.schemas
文件,指定xsd文件位置 - 编写标签处理器类,继承
BeanDefinitionParser
,重写它点parse
方法
下面我们主要来分析BeanDefinitionParser
标签处理器怎么来处理的?
- dubbo的标签解析代码很长,主要的功能就是把dubbo服务的标签解析成
ServiceBean
的BeanDefinition
并且给他赋予各个属性的值. - 在解析dubbo服务xml的时候,spring中的bean对象还没有创建好,这个时候需要dubbo服务实现类的bean对象,是获取不到的,只能使用它的bean名称,使用bean名称的占位符对象
RuntimeBeanReference
完成属性填充,对应配置文件内容如下:
<bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>
<dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService" version="1"/>
如果导出时的Dubbo接口实现类是使用class
属性填写的全路径类名称,那么在设置ServiceBean
的BeanDefinition
使用的属性就是使用BeanDefinitionHolder
<dubbo:service interface="org.apache.dubbo.demo.DemoService"
class="org.apache.dubbo.demo.provider.DemoServiceImpl"
version="1"/>
BeanDefinitionHolder
和RuntimeBeanReference
都是在属性填充的时候会解析出他们对应的真正的bean对象
注解方式
使用@EnableDubbo
注解开始 查看@DubboService
@DubboRefence
解析过程
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@EnableDubboConfig
@DubboComponentScan
public @interface EnableDubbo {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DubboComponentScanRegistrar.class)
public @interface DubboComponentScan {}
从@EnableDubbo
注解代码中可以看出来,使用了@Import
注解导入了DubboComponentScanRegistrar
类进行服务导出解析
@DubboService
注解通过DubboComponentScanRegistrar
添加了服务导出的解析类
public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
//解析@service
registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);
// @since 2.7.6 Register the common beans
registerCommonBeans(registry);
}
private void registerServiceAnnotationBeanPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationBeanPostProcessor.class);
builder.addConstructorArgValue(packagesToScan);
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
}
}
ServiceClassPostProcessor
是 ServiceAnnotationBeanPostProcessor
的父类,它实现了BeanDefinitionRegistryPostProcessor
接口,可以往BeanFactory
中添加BeanDefinition
public class ServiceClassPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,
ResourceLoaderAware, BeanClassLoaderAware {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// @since 2.7.5
registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME, DubboBootstrapApplicationListener.class);
Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
//注册@DubboService
registerServiceBeans(resolvedPackagesToScan, registry);
} else {
if (logger.isWarnEnabled()) {
logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
}
}
}
}
总结
- 通过注解或者 xml导出的每个dubbo服务 最后都会变成变成一个
ServiceBean extend ServiceConfig
- 服务导出都是借助spring中的扩展完成的
BeanDefinition
以及bean对象生成