一、 构造ServiceBean
ServiceBean
继承与ServiceConfig
,构造完成,并注册后。在触发ServiceBean
的onApplicationEvent
事 件后,进行dubbo意义上的provider注册zookeeper。一个ServiceBean
就对应一个@Service的注解,注解的属性其实和在配置文件中是一致的。
首先dubbo使用ServiceAnnotationBeanPostProcessor
实现spring的BeanDefinitionRegistryPostProcessor
接口。这个接口是用来注册在配置文件或者注解中配置的javaBean.BeanDefinitionRegistryPostProcessor
提供了让我们对BeanDefinition进行自定义注册的方法,如果Spring中的默认配置方式不能满足你的要求,就可以通过实现BeanDefinitionRegistryPostProcessor
接口来进行扩展。(详情:http://rason.me/2016/12/16/BeanDefinitionRegistryPostProcessor/)
1.首先看下这个接口的方法:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}
这个方法实现后,spring传入BeanDefinitionRegistry
(Bean 定义注册),然后并调用方法。只需要在其中写注册的bean的业务。
再看看实现:
private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
DubboClassPathBeanDefinitionScanner scanner =
new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
scanner.setBeanNameGenerator(beanNameGenerator);
//过滤器,保留带Service注解的类
scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class));
for (String packageToScan : packagesToScan) {
// Registers @Service Bean first
scanner.scan(packageToScan);
// Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not.
Set<BeanDefinitionHolder> beanDefinitionHolders =
findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);
if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
registerServiceBean(beanDefinitionHolder, registry, scanner);
}
}
通过DubboClassPathBeanDefinitionScanner
进行扫描,配置注解的service类并注册他们,把scanner传递下去。然后从中过滤出带有@service注解的bean包装成BeanDefinitionHolder
传递给registerServiceBean(beanDefinitionHolder, registry, scanner)
方法。
2.然后看看registerServiceBean做了什么。
private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,DubboClassPathBeanDefinitionScanner scanner) {
Class<?> beanClass = resolveClass(beanDefinitionHolder);
Service service = findAnnotation(beanClass, Service.class);
Class<?> interfaceClass = resolveServiceInterfaceClass(beanClass, service);
String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
//构造bean定义
AbstractBeanDefinition serviceBeanDefinition =
buildServiceBeanDefinition(service, interfaceClass, annotatedServiceBeanName);
// ServiceBean Bean name
String beanName = generateServiceBeanName(service, interfaceClass, annotatedServiceBeanName);
if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
registry.registerBeanDefinition(beanName, serviceBeanDefinition);
if (logger.isInfoEnabled()) {
logger.warn("The BeanDefinition[" + serviceBeanDefinition +
"] of ServiceBean has been registered with name : " + beanName);
}
}
}
通过上一步BeanDefinitionHolder
解析出字节码对象,接口的字节码,bean的名字包装为AbstractBeanDefinition
给BeanDefinitionRegistry
(spring)进行注册。
3.看看buildServiceBeanDefinition是怎么构造AbstractBeanDefinition的。
//以ServiceBean为根对象
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
String[] ignoreAttributeNames = of("provider", "monitor", "application", "module", "registry", "protocol", "interface");
propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(service, environment, ignoreAttributeNames));
// References "ref" property to annotated-@Service Bean
addPropertyReference(builder, "ref", annotatedServiceBeanName);
// Set interface
builder.addPropertyValue("interface", interfaceClass.getName());
/**
* Add {@link org.apache.dubbo.config.ProviderConfig} Bean reference
*/
String providerConfigBeanName = service.provider();
if (StringUtils.hasText(providerConfigBeanName)) {
addPropertyReference(builder, "provider", providerConfigBeanName);
}
/**
* Add {@link org.apache.dubbo.config.MonitorConfig} Bean reference
*/
String monitorConfigBeanName = service.monitor();
if (StringUtils.hasText(monitorConfigBeanName)) {
addPropertyReference(builder, "monitor", monitorConfigBeanName);
}
/**
* Add {@link org.apache.dubbo.config.ApplicationConfig} Bean reference
*/
String applicationConfigBeanName = service.application();
if (StringUtils.hasText(applicationConfigBeanName)) {
addPropertyReference(builder, "application", applicationConfigBeanName);
}
/**
* Add {@link org.apache.dubbo.config.ModuleConfig} Bean reference
*/
String moduleConfigBeanName = service.module();
if (StringUtils.hasText(moduleConfigBeanName)) {
addPropertyReference(builder, "module", moduleConfigBeanName);
}
这里就是添加@Service注解的属性引用。源码中标记的Add Bean reference很多,未展示完。然后我跳回到上一步的registry.registerBeanDefinition
去看看。他就是告诉spring我注册了这样一个javaBean。这就是构造了一个提供者的过程。
rootBeanDefinition(ServiceBean.class);
这段代码告诉我们这BeanDefinition
是以ServiceBean.class
为根的,所以其实就是在构造ServiceBean
.
二、总结
可以实现BeanDefinitionRegistryPostProcessor进行自定义扫描注解并注册自己的java bean.其实也就是给自己的代码集成Spring IOC.
网友评论