本文基于 Dubbo 2.7.1-SNAPSHOT 版本,望知悉。
1. 概述
在 Dubbo 提供的几种方式中,注解配置慢慢变成大家最常用的方式。
如果胖友不熟悉,可以查看如下文档:
2. 使用示例
我们来看看 dubbo-demo-annotation
项目下的 dubbo-demo-annotation-provider
子项目提供的 Dubbo Provider 示例。代码如下:
// Application.java |
<1>
处,使用@EnableDubbo
注解,配置扫描"org.apache.dubbo.demo.provider"
目录下的@Service
和@Reference
Bean 对象。<2>
处,使用@PropertySource
注解,导入"classpath:/spring/dubbo-provider.properties"
配置文件。<3>
处,通过@Bean
注解方法,创建 RegistryConfig Bean 对象,即注册中心。- 通过使用 Java Config + 注解的方式,相比 XML 来说,会更加熟悉一些~
下面,我们就来看看具体的源码落。本文涉及的类,主要如下图所示:类
3. @EnableDubbo
org.apache.dubbo.config.spring.context.annotation.@EnableDubbo
注解,是 @EnableDubboConfig
和 @DubboComponentScan
的组合注解,使用时更加便利。代码如下:
// EnableDubbo.java |
- 注意看下具体的注释。
通过
@EnableDubbo
可以在指定的包名下(通过scanBasePackages
属性),或者指定的类中(通过scanBasePackageClasses
属性)扫描 Dubbo 的服务提供者(以@Service
注解)以及 Dubbo 的服务消费者(以@Reference
注解)。扫描到 Dubbo 的服务提供方和消费者之后,对其做相应的组装并初始化,并最终完成服务暴露或者引用的工作。
4. @EnableDubboConfig
org.apache.dubbo.config.spring.context.annotation.@EnableDubboConfig
注解,开启 Dubbo 配置。代码如下:
// EnableDubboConfig.java |
- 关于
multiple
属性,可能第一眼会有点懵逼,那咋整呢?- 第一步,可以看看 《Dubbo 新编程模型之外部化配置 ——
@EnableDubboConfig
》 对@EnableDubboConfig
注解的介绍。 - 第二步,我们在接下来会看具体的源码,会更易懂一些。
- 第一步,可以看看 《Dubbo 新编程模型之外部化配置 ——
@Import(DubboConfigConfigurationRegistrar.class)
注解,表明使用 DubboConfigConfigurationRegistrar 类进行导入。详细的,我们继续来看 「4.1 DubboConfigConfigurationRegistrar」 。
4.1 DubboConfigConfigurationRegistrar
org.apache.dubbo.config.spring.context.annotation.DubboConfigConfigurationRegistrar
,实现 ImportBeanDefinitionRegistrar 接口,处理 @EnableDubboConfig
注解,注册相应的 DubboConfigConfiguration 到 Spring 容器中。代码如下:
// DubboConfigConfigurationRegistrar.java |
- 根据
@EnableDubboConfig
注解上的multiple
属性的不同,创建 DubboConfigConfiguration.Multiple 或 DubboConfigConfiguration.Single 对象,注册到 Spring 容器中。
4.2 DubboConfigConfiguration
org.apache.dubbo.config.spring.beans.factory.annotation.DubboConfigConfiguration
,Dubbo AbstractConfig 配置类。代码如下:
// DubboConfigConfiguration.java |
- 乍眼一看,就是 Single 和 Multiple 内部类。其上都有
@@EnableDubboConfigBindings
和@EnableDubboConfigBinding
注解。- 前者 Single ,其上的注解,
prefix
都是单数。 - 后者 Multiple ,其上的注解,
prefix
都是复数,且有multiple = true
。
- 前者 Single ,其上的注解,
- 那么会有什么效果呢?我们继续往 「4.3 @@EnableDubboConfigBindings」 和 「4.4 @@EnableDubboConfigBinding」 看。
4.3 @EnableDubboConfigBindings
org.apache.dubbo.config.spring.context.annotation.@EnableDubboConfigBindings
注解,是 @EnableDubboConfigBinding
注解的数组。代码如下:
// EnableDubboConfigBindings.java |
@Import(DubboConfigBindingsRegistrar.class)
注解,表明使用 DubboConfigBindingsRegistrar 类进行导入。详细的,我们继续来看 「4.3.1 DubboConfigBindingsRegistrar」 。
4.3.1 DubboConfigBindingsRegistrar
org.apache.dubbo.config.spring.context.annotation.DubboConfigBindingsRegistrar
,实现 ImportBeanDefinitionRegistrar、EnvironmentAware 接口,处理 @EnableDubboConfigBindings
注解,注册相应的 Dubbo AbstractConfig 到 Spring 容器中。代码如下:
// DubboConfigBindingsRegistrar.java |
<1.1>
、<1.2>
处,获得@EnableDubboConfigBindings
注解,从而后面获得内部的@EnableDubboConfigBinding
注解的数组。<2>
处,创建 DubboConfigBindingRegistrar 对象,并设置environment
属性。<3>
处,遍历annotationAttributes
数组,使用registrar
,调用DubboConfigBindingRegistrar#registerBeanDefinitions(AnnotationAttributes attributes, BeanDefinitionRegistry registry)
方法,进行逐个@EnableDubboConfigBinding
注解的注册对应的 Bean 。- 在下文中,我们会看到 DubboConfigBindingRegistrar 本来就是用来处理
EnableDubboConfigBinding
注解。
4.4 @EnableDubboConfigBinding
org.apache.dubbo.config.spring.context.annotation.@EnableDubboConfigBinding
注解,代码如下:
// EnableDubboConfigBinding.java |
- 每个属性,看其上的代码注释。
@Import(DubboConfigBindingRegistrar.class)
注解,表明使用 DubboConfigBindingRegistrar 类进行导入。详细的,我们继续来看 「4.4.1 DubboConfigBindingRegistrar」 。
4.4.1 DubboConfigBindingRegistrar
org.apache.dubbo.config.spring.context.annotation.DubboConfigBindingRegistrar
,实现 ImportBeanDefinitionRegistrar、EnvironmentAware 接口,处理 @EnableDubboConfigBinding
注解,注册相应的 Dubbo AbstractConfig 到 Spring 容器中。
4.4.1.1 registerBeanDefinitions
实现 #registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)
方法,处理 @EnableDubboConfigBinding
注解,注册相应的 Dubbo AbstractConfig 到 Spring 容器中。代码如下:
// DubboConfigBindingRegistrar.java |
<1>
处,获得@EnableDubboConfigBinding
注解。<2>
注册配置对应的 Bean Definition 对象。😈 这里有个知识点要补充下,Spring 在创建 Bean 之前,会将 XML 配置或者注解配置,先解析成对应的 BeanDefinition 对象,然后在创建 Bean 对象。<2.1>
处,获得prefix
属性。<2.2>
处,获得type
属性,即 AbstractConfig 的实现类。<2.3>
处,获得multiple
属性。<2.4>
处,调用#registerDubboConfigBeans(String prefix, Class<? extends AbstractConfig> configClass, boolean multiple, BeanDefinitionRegistry registry)
方法,注册 Dubbo Config Bean 对象。
4.4.1.2 registerDubboConfigBeans
#registerDubboConfigBeans(String prefix, Class<? extends AbstractConfig> configClass, boolean multiple, BeanDefinitionRegistry registry)
方法,注册 Dubbo Config Bean 对象。代码如下:
// DubboConfigBindingRegistrar.java |
<1.1>
处,调用PropertySourcesUtils#getSubProperties(Iterable<PropertySource<?>> propertySources, String prefix)
方法,获得prefix
开头的配置属性。因为,后续会用这个属性,设置到创建的 Bean 对象中。<1.2>
处,如果配置属性为空,则无需创建。<2>
处,根据multiple
的值,调用不同的方法,获得配置属性对应的 Bean 名字的集合。代码如下:// DubboConfigBindingRegistrar.java
// 例如:dubbo.application.${beanName}.name=dubbo-demo-annotation-provider
private Set<String> resolveMultipleBeanNames(Map<String, Object> properties) {
Set<String> beanNames = new LinkedHashSet<String>();
for (String propertyName : properties.keySet()) {
// 获取上述示例的 ${beanName} 字符串
int index = propertyName.indexOf(".");
if (index > 0) {
String beanName = propertyName.substring(0, index);
beanNames.add(beanName);
}
}
return beanNames;
}
// 例如:dubbo.application.name=dubbo-demo-annotation-provider
private String resolveSingleBeanName(Map<String, Object> properties, Class<? extends AbstractConfig> configClass,
BeanDefinitionRegistry registry) {
// 获得 Bean 的名字
String beanName = (String) properties.get("id");
// 如果定义,基于 Spring 提供的机制,生成对应的 Bean 的名字。例如说:org.apache.dubbo.config.ApplicationConfig#0
if (!StringUtils.hasText(beanName)) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(configClass);
beanName = BeanDefinitionReaderUtils.generateBeanName(builder.getRawBeanDefinition(), registry);
}
return beanName;
}- 这两个方法,看看我提供的示例。
#resolveMultipleBeanNames(Map<String, Object> properties)
方法,可能比较难理解一点。胖友可以增加如下到配置文件中:# application.properties
dubbo.applications.x.name=biu
dubbo.applications.y.name=biubiubiu- 此时,你需要指定
@Service
Bean 使用哪个应用。
- 此时,你需要指定
<3>
处,遍历beanNames
数组,逐个注册。<3.1>
处,调用#registerDubboConfigBean(String beanName, Class<? extends AbstractConfig> configClass, BeanDefinitionRegistry registry)
方法,注册 Dubbo Config Bean 对象。代码如下:// DubboConfigBindingRegistrar.java
private void registerDubboConfigBean(String beanName, Class<? extends AbstractConfig> configClass,
BeanDefinitionRegistry registry) {
// 创建 BeanDefinitionBuilder 对象
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(configClass);
// 获得 AbstractBeanDefinition 对象
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
// 注册到 registry 中
registry.registerBeanDefinition(beanName, beanDefinition);
if (log.isInfoEnabled()) {
log.info("The dubbo config bean definition [name : " + beanName + ", class : " + configClass.getName() + "] has been registered.");
}
}- 此时,仅仅是通过酱紫的方式,创建了一个 Dubbo Config Bean 对象,并没有将配置属性,设置到该对象中。答案在
<3.2>
中。
- 此时,仅仅是通过酱紫的方式,创建了一个 Dubbo Config Bean 对象,并没有将配置属性,设置到该对象中。答案在
<3.2>
处,调用#registerDubboConfigBindingBeanPostProcessor(String prefix, String beanName, boolean multiple, BeanDefinitionRegistry registry)
方法,注册 Dubbo Config 对象对象的 DubboConfigBindingBeanPostProcessor 对象。代码如下:// DubboConfigBindingRegistrar.java
private void registerDubboConfigBindingBeanPostProcessor(String prefix, String beanName, boolean multiple,
BeanDefinitionRegistry registry) {
// 创建 BeanDefinitionBuilder 对象
Class<?> processorClass = DubboConfigBindingBeanPostProcessor.class;
BeanDefinitionBuilder builder = rootBeanDefinition(processorClass);
// 添加构造方法的参数为 actualPrefix 和 beanName 。即,创建 DubboConfigBindingBeanPostProcessor 对象,需要这两个构造参数
String actualPrefix = multiple ? PropertySourcesUtils.normalizePrefix(prefix) + beanName : prefix;
builder.addConstructorArgValue(actualPrefix).addConstructorArgValue(beanName);
// 获得 AbstractBeanDefinition 对象
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
// 设置 role 属性
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册到 registry 中
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
if (log.isInfoEnabled()) {
log.info("The BeanPostProcessor bean definition [" + processorClass.getName() + "] for dubbo config bean [name : " + beanName + "] has been registered.");
}
}- 因为此时 Dubbo Config Bean 对象还未创建,所以需要等后续它真的创建之后,使用 DubboConfigBindingBeanPostProcessor 类,实现对对象(Bean 对象)的配置输入的设置。
至此,我们发现,需要继续挖掘,让我们继续来看 「DubboConfigBindingBeanPostProcessor」 类。
4.5 DubboConfigBindingBeanPostProcessor
org.apache.dubbo.config.spring.beans.factory.annotation.DubboConfigBindingBeanPostProcessor
,实现 BeanPostProcessor、ApplicationContextAware、InitializingBean 接口,处理 Dubbo AbstractConfig Bean 的配置属性注入。
4.5.1 构造方法
// DubboConfigBindingBeanPostProcessor.java |
- 所以,我们在上文中会看到,创建 DubboConfigBindingBeanPostProcessor Bean 时,会有
builder.addConstructorArgValue(actualPrefix).addConstructorArgValue(beanName);
一段的代码。
4.5.2 afterPropertiesSet
#afterPropertiesSet()
方法,设置 dubboConfigBinder
属性。代码如下:
// DubboConfigBindingBeanPostProcessor.java |
- 关于 DefaultDubboConfigBinder 类,我们在下面的小节先来瞅瞅。
4.5.2.1 DubboConfigBinder
org.apache.dubbo.config.spring.context.properties.DubboConfigBinder
,继承 EnvironmentAware 接口,Dubbo Config Binder 接口。代码如下:
// DubboConfigBinder.java |
- 后续的实现,我们会看到基于 Spring DataBinder 来实现。不了解 DataBinder 的胖友,可以看看 《Spring 验证、数据绑定和类型转换》 文章。
4.5.2.2 DubboConfigBinder
org.apache.dubbo.config.spring.context.properties.AbstractDubboConfigBinder
,实现 DubboConfigBinder 接口,DubboConfigBinder 的抽象基类。代码如下:
// AbstractDubboConfigBinder.java |
- 提供默认的属性。
4.5.2.3 DefaultDubboConfigBinder
org.apache.dubbo.config.spring.context.properties.DefaultDubboConfigBinder
,继承 AbstractDubboConfigBinder 抽象类,使用 Spring DataBinder ,将配置属性设置到 Dubbo Config 对象中。代码如下:
// DefaultDubboConfigBinder.java |
- 比较简单,胖友自己瞅一眼代码即可。
在 《Dubbo 源码分析 —— 集成 Spring Boot》 中,我们可以看到另外一个 AbstractDubboConfigBinder 的实现类 RelaxedDubboConfigBinder ,它是基于 Spring Boot Binder 进行实现。😈 因为艿艿没有深入了解过 Spring Boot Binder 相关,所以还说不出和 Spring DataBinder 的区别在哪。orz
4.5.3 postProcessBeforeInitialization
实现 #postProcessBeforeInitialization(Object bean, String beanName)
方法,设置配置属性到 Dubbo Config 中。代码如下:
// DubboConfigBindingBeanPostProcessor.java |
至此,Dubbo Config 对象的创建和属性设置,已经完成。如果胖友还是有点懵逼,可以调试一次,没有什么复杂逻辑哟。
5. @DubboComponentScan
org.apache.dubbo.config.spring.context.annotation.@DubboComponentScan
注解,配置要扫描 @Service
和 @Reference
注解的包或者类们,从而创建对应的 Bean 对象。代码如下:
// DubboComponentScan.java |
@Import(DubboComponentScanRegistrar.class)
注解,表明使用 DubboComponentScanRegistrar 类进行导入。详细的,我们继续来看 「5.1 DubboComponentScanRegistrar」 。
5.1 DubboComponentScanRegistrar
org.apache.dubbo.config.spring.context.annotation.DubboComponentScanRegistrar
,实现 ImportBeanDefinitionRegistrar 接口,处理 @DubboComponentScan
注解,注册相应的 ServiceAnnotationBeanPostProcessor 和 ReferenceAnnotationBeanPostProcessor 到 Spring 容器中。代码如下:
// DubboComponentScanRegistrar.java |
<1>
处,调用#getPackagesToScan(AnnotationMetadata metadata)
方法,获得要扫描的包。代码如下:// DubboComponentScanRegistrar.java
private Set<String> getPackagesToScan(AnnotationMetadata metadata) {
// 获得 @DubboComponentScan 注解
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(DubboComponentScan.class.getName()));
// 获得其上的属性
String[] basePackages = attributes.getStringArray("basePackages");
Class<?>[] basePackageClasses = attributes.getClassArray("basePackageClasses");
String[] value = attributes.getStringArray("value");
// Appends value array attributes
// 情况一,将属性添加到 packagesToScan 集合中
Set<String> packagesToScan = new LinkedHashSet<String>(Arrays.asList(value));
packagesToScan.addAll(Arrays.asList(basePackages));
for (Class<?> basePackageClass : basePackageClasses) {
packagesToScan.add(ClassUtils.getPackageName(basePackageClass));
}
// 情况二,如果 packagesToScan 为空,则默认使用注解类所在的包
if (packagesToScan.isEmpty()) {
return Collections.singleton(ClassUtils.getPackageName(metadata.getClassName()));
}
return packagesToScan;
}- 有两种情况,胖友看的时候,要注意下。
<2>
处,调用#registerServiceAnnotationBeanPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry)
方法,创建 ServiceAnnotationBeanPostProcessor Bean 对象,后续扫描@Service
注解的类,创建对应的 Service Bean 对象。代码如下:// DubboComponentScanRegistrar.java
private void registerServiceAnnotationBeanPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
// 创建 BeanDefinitionBuilder 对象
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ServiceAnnotationBeanPostProcessor.class);
// 设置构造方法参数为 packagesToScan ,即 BeanDefinitionBuilder 扫描该包
builder.addConstructorArgValue(packagesToScan);
// 设置 role 属性
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 获得 AbstractBeanDefinition 对象
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
// 注册到 registry 中
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
}- 关于 ServiceAnnotationBeanPostProcessor 类,我们在 「5.2 ServiceAnnotationBeanPostProcessor」 中,详细解析。
<3>
处,调用#registerReferenceAnnotationBeanPostProcessor(BeanDefinitionRegistry registry)
方法,创建 ReferenceAnnotationBeanPostProcessor Bean 对象,后续扫描@Reference
注解的类,创建对应的 Reference Bean 对象。代码如下:// DubboComponentScanRegistrar.java
private void registerReferenceAnnotationBeanPostProcessor(BeanDefinitionRegistry registry) {
// Register @Reference Annotation Bean Processor
BeanRegistrar.registerInfrastructureBean(registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class);
}
// BeanRegistrar.java
public static void registerInfrastructureBean(BeanDefinitionRegistry beanDefinitionRegistry,
String beanName, Class<?> beanType) {
// 不存在 beanName 对应的 BeanDefinition 对象
if (!beanDefinitionRegistry.containsBeanDefinition(beanName)) {
// 创建 RootBeanDefinition 对象
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanType);
// 设置 role
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册到 beanDefinitionRegistry 中
beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
}
}- 关于 ReferenceAnnotationBeanPostProcessor 类,我们在 「5.3 ReferenceAnnotationBeanPostProcessor」 中,详细解析。
5.2 ServiceAnnotationBeanPostProcessor
org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationBeanPostProcessor
,实现 BeanDefinitionRegistryPostProcessor、EnvironmentAware、ResourceLoaderAware、BeanClassLoaderAware 接口,扫描 @Service
注解的类,创建对应的 Spring BeanDefinition 对象,从而创建 Dubbo Service Bean 对象。
5.2.1 构造方法
// ServiceAnnotationBeanPostProcessor.java |
5.2.2 postProcessBeanDefinitionRegistry
实现 #postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
方法,扫描 @Service
注解的类,创建对应的 Spring BeanDefinition 对象,从而创建 Dubbo Service Bean 对象。代码如下:
// ServiceAnnotationBeanPostProcessor.java |
<1>
处,调用#resolvePackagesToScan(Set<String> packagesToScan)
方法,解析packagesToScan
集合。因为,可能存在占位符。代码如下:// ServiceAnnotationBeanPostProcessor.java
private Set<String> resolvePackagesToScan(Set<String> packagesToScan) {
Set<String> resolvedPackagesToScan = new LinkedHashSet<String>(packagesToScan.size());
// 遍历 packagesToScan 数组
for (String packageToScan : packagesToScan) {
if (StringUtils.hasText(packageToScan)) {
// 解析可能存在的占位符
String resolvedPackageToScan = environment.resolvePlaceholders(packageToScan.trim());
// 添加到 resolvedPackagesToScan 中
resolvedPackagesToScan.add(resolvedPackageToScan);
}
}
return resolvedPackagesToScan;
}<2>
处,调用#registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry)
方法,扫描packagesToScan
包,创建对应的 Spring BeanDefinition 对象,从而创建 Dubbo Service Bean 对象。详细解析,见 「5.2.3 resolvePackagesToScan」 中。
5.2.3 resolvePackagesToScan
#registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry)
方法,扫描 packagesToScan
包,创建对应的 Spring BeanDefinition 对象,从而创建 Dubbo Service Bean 对象。代码如下:
// ServiceAnnotationBeanPostProcessor.java |
<1.1>
处,创建 DubboClassPathBeanDefinitionScanner 对象。它是用于扫描指定包下符合条件的类,用于将每个符合条件的类,创建对应的 BeanDefinition 对象,从而创建 Bean 。关于 DubboClassPathBeanDefinitionScanner 类,胖友点击 链接 瞅一眼即可。<1.2>
处,调用#resolveBeanNameGenerator(BeanDefinitionRegistry registry)
方法,获得 BeanNameGenerator 对象,并设置beanNameGenerator
到scanner
中。代码如下:// ServiceAnnotationBeanPostProcessor.java
/**
* It'd better to use BeanNameGenerator instance that should reference
* {@link ConfigurationClassPostProcessor#componentScanBeanNameGenerator},
* thus it maybe a potential problem on bean name generation.
*
* @param registry {@link BeanDefinitionRegistry}
* @return {@link BeanNameGenerator} instance
* @see SingletonBeanRegistry
* @see AnnotationConfigUtils#CONFIGURATION_BEAN_NAME_GENERATOR
* @see ConfigurationClassPostProcessor#processConfigBeanDefinitions
* @since 2.5.8
*/
"Duplicates") (
private BeanNameGenerator resolveBeanNameGenerator(BeanDefinitionRegistry registry) {
BeanNameGenerator beanNameGenerator = null;
// 如果是 SingletonBeanRegistry 类型,从中获得对应的 BeanNameGenerator Bean 对象
if (registry instanceof SingletonBeanRegistry) {
SingletonBeanRegistry singletonBeanRegistry = SingletonBeanRegistry.class.cast(registry);
beanNameGenerator = (BeanNameGenerator) singletonBeanRegistry.getSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
}
// 如果不存在,则创建 AnnotationBeanNameGenerator 对象
if (beanNameGenerator == null) {
if (logger.isInfoEnabled()) {
logger.info("BeanNameGenerator bean can't be found in BeanFactory with name [" + CONFIGURATION_BEAN_NAME_GENERATOR + "]");
logger.info("BeanNameGenerator will be a instance of " + AnnotationBeanNameGenerator.class.getName() + " , it maybe a potential problem on bean name generation.");
}
beanNameGenerator = new AnnotationBeanNameGenerator();
}
return beanNameGenerator;
}<1.3>
处,设置过滤获得带有@Service
注解的类。关于@Service
注解的具体的属性,本文就不过分介绍,胖友自己瞅瞅。<2>
处,遍历packagesToScan
数组。<2.1>
处,调用DubboClassPathBeanDefinitionScanner#scan(String... basePackages)
方法,执行扫描。<2.2>
处,调用#findServiceBeanDefinitionHolders(ClassPathBeanDefinitionScanner scanner, String packageToScan, BeanDefinitionRegistry registry, BeanNameGenerator beanNameGenerator)
方法,创建每个在packageToScan
扫描到的类,对应的 BeanDefinitionHolder 对象,返回 BeanDefinitionHolder 集合。详细解析 ,见 「5.2.4 findServiceBeanDefinitionHolders」 中。<2.3>
处,调用#registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry, DubboClassPathBeanDefinitionScanner scanner)
方法,注册到registry
中。详细解析,见 「5.2.5 registerServiceBean」 中。
5.2.4 findServiceBeanDefinitionHolders
#findServiceBeanDefinitionHolders(ClassPathBeanDefinitionScanner scanner, String packageToScan, BeanDefinitionRegistry registry, BeanNameGenerator beanNameGenerator)
方法,创建每个在 packageToScan
扫描到的类,对应的 BeanDefinitionHolder 对象,返回 BeanDefinitionHolder 集合。代码如下:
// ServiceAnnotationBeanPostProcessor.java |
5.2.5 registerServiceBean
#registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry, DubboClassPathBeanDefinitionScanner scanner)
方法,注册到 registry
中。代码如下:
// ServiceAnnotationBeanPostProcessor.java |
<1.1>
处,调用#resolveClass(BeanDefinitionHolder beanDefinitionHolder)
方法,解析返回 Bean 的类。代码如下:// ServiceAnnotationBeanPostProcessor.java
private Class<?> resolveClass(BeanDefinitionHolder beanDefinitionHolder) {
BeanDefinition beanDefinition = beanDefinitionHolder.getBeanDefinition();
return resolveClass(beanDefinition);
}
private Class<?> resolveClass(BeanDefinition beanDefinition) {
String beanClassName = beanDefinition.getBeanClassName();
return ClassUtils.resolveClassName(beanClassName, classLoader);
}- 因为 BeanDefinition 的
beanClassName
是 String 类型,所以得转换成 Class 类型。
- 因为 BeanDefinition 的
<1.2>
处,获得@Service
注解。<1.3>
处,调用#resolveServiceInterfaceClass(Class<?> annotatedServiceBeanClass, Service service)
方法,获得 Service 接口。代码如下:// ServiceAnnotationBeanPostProcessor.java
"Duplicates") (
private Class<?> resolveServiceInterfaceClass(Class<?> annotatedServiceBeanClass, Service service) {
// 首先,从注解本身上获得
Class<?> interfaceClass = service.interfaceClass();
if (void.class.equals(interfaceClass)) { // 一般是满足的
interfaceClass = null;
// 获得 @Service 注解的 interfaceName 属性。
String interfaceClassName = service.interfaceName();
// 如果存在,获得其对应的类
if (StringUtils.hasText(interfaceClassName)) {
if (ClassUtils.isPresent(interfaceClassName, classLoader)) {
interfaceClass = ClassUtils.resolveClassName(interfaceClassName, classLoader);
}
}
}
// <X>【一般情况下,使用这个】获得不到,则从被注解的类上获得其实现的首个接口
if (interfaceClass == null) {
Class<?>[] allInterfaces = annotatedServiceBeanClass.getInterfaces();
if (allInterfaces.length > 0) {
interfaceClass = allInterfaces[0];
}
}
Assert.notNull(interfaceClass, "@Service interfaceClass() or interfaceName() or interface class must be present!");
Assert.isTrue(interfaceClass.isInterface(), "The type that was annotated @Service is not an interface!");
return interfaceClass;
}- 虽然代码比较长,但是重点看
<X>
处,从被注解的类上获得其实现的首个接口。
- 虽然代码比较长,但是重点看
<1.4>
处,获得 Bean 的名字。<1.5>
处,调用#buildServiceBeanDefinition(Service service, Class<?> interfaceClass, String annotatedServiceBeanName)
方法,创建 AbstractBeanDefinition 对象。代码如下:// ServiceAnnotationBeanPostProcessor.java
"Duplicates") (
private AbstractBeanDefinition buildServiceBeanDefinition(Service service, Class<?> interfaceClass, String annotatedServiceBeanName) {
// 创建 BeanDefinitionBuilder 对象
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ServiceBean.class);
// 获得 AbstractBeanDefinition 对象
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
// 获得 MutablePropertyValues 属性。后续 ,通过向它添加属性,设置到 BeanDefinition 中,即 Service Bean 中。
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
// <X> 创建 AnnotationPropertyValuesAdapter 对象,添加到 propertyValues 中。
// 此处,是将注解上的属性,设置到 propertyValues 中
String[] ignoreAttributeNames = of("provider", "monitor", "application", "module", "registry", "protocol", "interface", "interfaceName"); // 忽略的属性,下面进行单独设置。
propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(service, environment, ignoreAttributeNames));
// References "ref" property to annotated-@Service Bean
// 设置 ref 属性指向的 Service Bean 名字
addPropertyReference(builder, "ref", annotatedServiceBeanName);
// Set interface 设置 Service 接口类全类名
builder.addPropertyValue("interface", interfaceClass.getName());
/**
* Add {@link org.apache.dubbo.config.ProviderConfig} Bean reference
*
* 添加 provider 属性对应的 ProviderConfig Bean 对象
*/
String providerConfigBeanName = service.provider();
if (StringUtils.hasText(providerConfigBeanName)) {
addPropertyReference(builder, "provider", providerConfigBeanName);
}
/**
* Add {@link org.apache.dubbo.config.MonitorConfig} Bean reference
*
* 添加 monitor 属性对应的 MonitorConfig Bean 对象
*/
String monitorConfigBeanName = service.monitor();
if (StringUtils.hasText(monitorConfigBeanName)) {
addPropertyReference(builder, "monitor", monitorConfigBeanName);
}
/**
* Add {@link org.apache.dubbo.config.ApplicationConfig} Bean reference
*
* 添加 application 属性对应的 ApplicationConfig Bean 对象
*/
String applicationConfigBeanName = service.application();
if (StringUtils.hasText(applicationConfigBeanName)) {
addPropertyReference(builder, "application", applicationConfigBeanName);
}
/**
* Add {@link org.apache.dubbo.config.ModuleConfig} Bean reference
*
* 添加 module 属性对应的 ModuleConfig Bean 对象
*/
String moduleConfigBeanName = service.module();
if (StringUtils.hasText(moduleConfigBeanName)) {
addPropertyReference(builder, "module", moduleConfigBeanName);
}
/**
* Add {@link org.apache.dubbo.config.RegistryConfig} Bean reference
*
* 添加 registries 属性对应的 RegistryConfig Bean 数组(一个或多个)
*/
String[] registryConfigBeanNames = service.registry();
List<RuntimeBeanReference> registryRuntimeBeanReferences = toRuntimeBeanReferences(registryConfigBeanNames);
if (!registryRuntimeBeanReferences.isEmpty()) {
builder.addPropertyValue("registries", registryRuntimeBeanReferences);
}
/**
* Add {@link org.apache.dubbo.config.ProtocolConfig} Bean reference
*
* 添加 protocols 属性对应的 ProtocolConfig Bean 数组(一个或多个)
*/
String[] protocolConfigBeanNames = service.protocol();
List<RuntimeBeanReference> protocolRuntimeBeanReferences = toRuntimeBeanReferences(protocolConfigBeanNames);
if (!protocolRuntimeBeanReferences.isEmpty()) {
builder.addPropertyValue("protocols", protocolRuntimeBeanReferences);
}
return builder.getBeanDefinition();
}
// RuntimeBeanReference ,在解析到依赖的Bean的时侯,解析器会依据依赖bean的name创建一个RuntimeBeanReference对像,将这个对像放入BeanDefinition的MutablePropertyValues中。
// 此处,和上面不太一样的原因,因为是多个
"Duplicates") (
private ManagedList<RuntimeBeanReference> toRuntimeBeanReferences(String... beanNames) {
ManagedList<RuntimeBeanReference> runtimeBeanReferences = new ManagedList<RuntimeBeanReference>();
if (!ObjectUtils.isEmpty(beanNames)) {
for (String beanName : beanNames) {
// 解析真正的 Bean 名字,如果有占位符的话
String resolvedBeanName = environment.resolvePlaceholders(beanName);
runtimeBeanReferences.add(new RuntimeBeanReference(resolvedBeanName));
}
}
return runtimeBeanReferences;
}
// 添加属性值是引用类型
private void addPropertyReference(BeanDefinitionBuilder builder, String propertyName, String beanName) {
String resolvedBeanName = environment.resolvePlaceholders(beanName);
builder.addPropertyReference(propertyName, resolvedBeanName);
}- 比较冗长,顺着往下看即可。
<X>
处,创建 AnnotationPropertyValuesAdapter 对象,添加到propertyValues
中。此处,是将注解上的属性,设置到propertyValues
中。也就是说,注解上的属性,自然的能够设置到后续创建的 Service Bean 的对象中。- 举个例子,如果说
@Service(version="1.0.0")
,那么这个版本号(version
),就可以设置到 Dubbo Service Bean 中去了。 - 关于
org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationPropertyValuesAdapter
类,就是上述的用途,比较简单,胖友点击 链接 查看即可。
- 举个例子,如果说
<2>
处,调用#generateServiceBeanName(Service service, Class<?> interfaceClass, String annotatedServiceBeanName)
方法,重新生成 Bean 的名字。代码如下:// ServiceAnnotationBeanPostProcessor.java
private String generateServiceBeanName(Service service, Class<?> interfaceClass, String annotatedServiceBeanName) {
ServiceBeanNameBuilder builder = ServiceBeanNameBuilder.create(service, interfaceClass, environment);
return builder.build();
}
// ServiceBeanNameBuilder.java
private static final String SEPARATOR = ":";
private final String interfaceClassName;
private final Environment environment;
// Optional
private String version;
private String group;
// ServiceBean:${interfaceClassName}:${version}:${group}
public String build() {
StringBuilder beanNameBuilder = new StringBuilder("ServiceBean");
// Required
append(beanNameBuilder, interfaceClassName);
// Optional
append(beanNameBuilder, version);
append(beanNameBuilder, group);
// Build
String rawBeanName = beanNameBuilder.toString();
// Resolve placeholders
return environment.resolvePlaceholders(rawBeanName);
}
private static void append(StringBuilder builder, String value) {
if (StringUtils.hasText(value)) {
builder.append(SEPARATOR).append(value);
}
}<3>
处,校验在scanner
中,是否已经存在beanName
。若不存在,则进行注册。
😈 整个逻辑,有点长长滴。胖友辛苦上下滑动,在瞅瞅。
5.3 ReferenceAnnotationBeanPostProcessor
org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor
,继承 AnnotationInjectedBeanPostProcessor 抽象类,实现 ApplicationContextAware、ApplicationListener 接口,扫描 @Reference
注解的类,创建对应的 Spring BeanDefinition 对象,从而创建 Dubbo Reference Bean 对象。
虽然
org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationInjectedBeanPostProcessor
放在 Dubbo 项目中,但是是 clone 自 https://github.com/alibaba/spring-context-support/blob/1.0.2/src/main/java/com/alibaba/spring/beans/factory/annotation/AnnotationInjectedBeanPostProcessor.java 类。所以呢,我们先不深究这个类,只要知道如下:
- 英文:Abstract generic {@link BeanPostProcessor} implementation for customized annotation that annotated injected-object.
- 中文:BeanPostProcessor 的抽象实现类,用于支持使用自定义注解,注入对象的属性。
- 此时,ReferenceAnnotationBeanPostProcessor 实现的就是 支持
@Reference
注解的属性注入。
相对来说,本节的 ReferenceAnnotationBeanPostProcessor ,会比上一节的 ServiceAnnotationBeanPostProcessor 复杂蛮多~ SO ,保持耐心哈。
5.3.1 构造方法
// ReferenceAnnotationBeanPostProcessor.java |
- 具体的每个变量的时候,结合下面来看。
5.3.2 doGetInjectedBean
实现 #doGetInjectedBean(Reference reference, Object bean, String beanName, Class<?> injectedType, InjectionMetadata.InjectedElement injectedElement)
方法,获得要注入的 @Reference
Bean 。代码如下:
// ReferenceAnnotationBeanPostProcessor.java |
<1>
处,调用#buildReferencedBeanName(Reference reference, Class<?> injectedType)
方法,获得 Reference Bean 的名字。代码如下:// ReferenceAnnotationBeanPostProcessor.java
private String buildReferencedBeanName(Reference reference, Class<?> injectedType) {
// 创建 Service Bean 的名字
ServiceBeanNameBuilder builder = ServiceBeanNameBuilder.create(reference, injectedType, getEnvironment());
return getEnvironment().resolvePlaceholders(builder.build()); // 这里,貌似重复解析占位符了。不过没啥影响~
}- 实际上,使用的就是 ServiceBeanNameBuilder 的逻辑,即和 Dubbo Service Bean 的名字,是 同一套。当然,这个也非常合理~
<2>
处,调用#buildReferenceBeanIfAbsent(String referencedBeanName, Reference reference, Class<?> referencedType, ClassLoader classLoader)
方法,创建(获得) ReferenceBean 对象。代码如下:// ReferenceAnnotationBeanPostProcessor.java
private ReferenceBean buildReferenceBeanIfAbsent(String referencedBeanName, Reference reference, Class<?> referencedType, ClassLoader classLoader)
throws Exception {
// 首先,从 referenceBeanCache 缓存中,获得 referencedBeanName 对应的 ReferenceBean 对象
ReferenceBean<?> referenceBean = referenceBeanCache.get(referencedBeanName);
// 然后,如果不存在,则进行创建。然后,添加到 referenceBeanCache 缓存中。
if (referenceBean == null) {
ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder
.create(reference, classLoader, applicationContext)
.interfaceClass(referencedType);
referenceBean = beanBuilder.build();
referenceBeanCache.put(referencedBeanName, referenceBean);
}
return referenceBean;
}- 其中,会使用 ReferenceBeanBuilder 类,构建 ReferenceBean 对象。关于它,我们稍后在 「5.3.4 ReferenceBeanBuilder」 来瞅瞅。实际上,和上面 ServiceBean 的构建,也差不了太多。
<3>
处,调用#cacheInjectedReferenceBean(String referencedBeanName, Reference reference, Class<?> referencedType, ClassLoader classLoader)
方法,缓存到injectedFieldReferenceBeanCache
orinjectedMethodReferenceBeanCache
中。代码如下:// ReferenceAnnotationBeanPostProcessor.java
private void cacheInjectedReferenceBean(ReferenceBean referenceBean, InjectionMetadata.InjectedElement injectedElement) {
if (injectedElement.getMember() instanceof Field) {
injectedFieldReferenceBeanCache.put(injectedElement, referenceBean);
} else if (injectedElement.getMember() instanceof Method) {
injectedMethodReferenceBeanCache.put(injectedElement, referenceBean);
}
}<4>
处,调用#buildProxy(String referencedBeanName, ReferenceBean referenceBean, Class<?> injectedType)
方法,创建 Proxy 代理对象。代码如下:// ReferenceAnnotationBeanPostProcessor.java
private Object buildProxy(String referencedBeanName, ReferenceBean referenceBean, Class<?> injectedType) {
InvocationHandler handler = buildInvocationHandler(referencedBeanName, referenceBean);
return Proxy.newProxyInstance(getClassLoader(), new Class[]{injectedType}, handler);
}
private InvocationHandler buildInvocationHandler(String referencedBeanName, ReferenceBean referenceBean) {
// 首先,从 localReferenceBeanInvocationHandlerCache 缓存中,获得 ReferenceBeanInvocationHandler 对象
ReferenceBeanInvocationHandler handler = localReferenceBeanInvocationHandlerCache.get(referencedBeanName);
// 然后,如果不存在,则创建 ReferenceBeanInvocationHandler 对象
if (handler == null) {
handler = new ReferenceBeanInvocationHandler(referenceBean);
}
// <X> 之后,根据引用的 Dubbo 服务是远程的还是本地的,做不同的处理。
// 【本地】判断如果 applicationContext 中已经初始化,说明是本地的 @Service Bean ,则添加到 localReferenceBeanInvocationHandlerCache 缓存中。
// 等到本地的 @Service Bean 暴露后,再进行初始化。
if (applicationContext.containsBean(referencedBeanName)) { // Is local @Service Bean or not ?
// ReferenceBeanInvocationHandler's initialization has to wait for current local @Service Bean has been exported.
localReferenceBeanInvocationHandlerCache.put(referencedBeanName, handler);
// 【远程】判断若果 applicationContext 中未初始化,说明是远程的 @Service Bean 对象,则立即进行初始化
} else {
// Remote Reference Bean should initialize immediately
handler.init();
}
return handler;
}- 比较复杂的是,
<X>
处,根据引用的 Dubbo 服务是远程的还是本地的,做不同的处理。为什么呢?- 远程的 Dubbo 服务,理论来说(不考虑对方挂掉的情况),是已经存在,此时可以进行加载引用。
- 本地的 Dubbo 服务,此时并未暴露,则先添加到
localReferenceBeanInvocationHandlerCache
中进行缓存。等后续的,通过 Spring 事件监听的功能,进行实现。详细的,我们在 「5.3.3 onApplicationEvent」 中会看到。
ReferenceBeanInvocationHandler ,是 ReferenceAnnotationBeanPostProcessor 的内部静态类,实现 Dubbo InvocationHandler 接口,代码如下:
// ReferenceAnnotationBeanPostProcessor#ReferenceBeanInvocationHandler.java
private static class ReferenceBeanInvocationHandler implements InvocationHandler {
/**
* ReferenceBean 对象
*/
private final ReferenceBean referenceBean;
/**
* Bean 对象
*/
private Object bean;
private ReferenceBeanInvocationHandler(ReferenceBean referenceBean) {
this.referenceBean = referenceBean;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 调用 bean 的对应的方法
return method.invoke(bean, args);
}
// 通过初始化方法,可以获得 `ReferenceBean.ref`
private void init() {
this.bean = referenceBean.get();
}
}- 重心在于
#init()
方法,可以调用ReferenceBean#get()
方法,进行引用的 Bean 的初始化,最后返回引用ref
。
- 重心在于
- 比较复杂的是,
5.3.3 onApplicationEvent
实现 #onApplicationEvent(ApplicationEvent event)
方法,代码如下:
// ReferenceAnnotationBeanPostProcessor.java |
- 重点在于处理 ServiceBeanExportedEvent 事件。处理时,如果判断
localReferenceBeanInvocationHandlerCache
中存在 ReferenceBeanInvocationHandler 对象,说明有它未初始化。后续,调用ReferenceBeanInvocationHandler#init()
方法,从而完成。这块,胖友结合 「5.2.2 doGetInjectedBean」 一起,是不是就明白了。 在 ServiceBean 暴露服务完成后,会发布 ServiceBeanExportedEvent 事件。代码如下:
// ServiceBean.java
private ApplicationEventPublisher applicationEventPublisher;
/**
* @since 2.6.5
*/
public void export() {
// 暴露服务
super.export();
// Publish ServiceBeanExportedEvent
// 发布事件
publishExportEvent();
}
/**
* @since 2.6.5
*/
private void publishExportEvent() {
// 创建 ServiceBeanExportedEvent 对象
ServiceBeanExportedEvent exportEvent = new ServiceBeanExportedEvent(this);
// 发布事件
applicationEventPublisher.publishEvent(exportEvent);
}org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent
,Service Bean 暴露完成事件。代码如下:// BeanExportedEvent.java
/**
* A {@link ApplicationEvent} after {@link ServiceBean} {@link ServiceBean#export() export} invocation
*
* @see ApplicationEvent
* @see ApplicationListener
* @see ServiceBean
* @since 2.6.5
*/
public class ServiceBeanExportedEvent extends ApplicationEvent {
/**
* Create a new ApplicationEvent.
*
* @param serviceBean {@link ServiceBean} bean
*/
public ServiceBeanExportedEvent(ServiceBean serviceBean) {
super(serviceBean);
}
/**
* Get {@link ServiceBean} instance
*
* @return non-null
*/
public ServiceBean getServiceBean() {
return (ServiceBean) super.getSource();
}
}
5.3.4 ReferenceBeanBuilder
org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceBeanBuilder
,继承 AbstractAnnotationConfigBeanBuilder 抽象类,ReferenceBean 的构建器。
考虑到 ReferenceBeanBuilder 类,就是
#build()
方法,我们就直接结合 AbstractAnnotationConfigBeanBuilder 抽象类,一起写了。
5.3.4.1 构造方法
// AbstractAnnotationConfigBeanBuilder.java |
- 其中,泛型
A
对应@Reference
注解,泛型B
对应 ReferenceBean 类。
5.3.4.2 build
#build()
方法,构造泛型 B
对象。此处,就是构造 ReferenceBean 对象。代码如下:
// AbstractAnnotationConfigBeanBuilder.java |
ReferenceBeanBuilder 主要对上面的抽象方法,进行具体实现。代码如下:
// ReferenceBeanBuilder.java
static final String[] IGNORE_FIELD_NAMES = of("application", "module", "consumer", "monitor", "registry")
protected ReferenceBean doBuild() {
// 创建 ReferenceBean 对象
return new ReferenceBean<>();
}
"Duplicates") (
protected void preConfigureBean(Reference reference, ReferenceBean referenceBean) {
Assert.notNull(interfaceClass, "The interface class must set first!");
// 创建 DataBinder 对象
DataBinder dataBinder = new DataBinder(referenceBean);
// Register CustomEditors for special fields
// 注册指定属性的自定义 Editor
dataBinder.registerCustomEditor(String.class, "filter", new StringTrimmerEditor(true));
dataBinder.registerCustomEditor(String.class, "listener", new StringTrimmerEditor(true));
dataBinder.registerCustomEditor(Map.class, "parameters", new PropertyEditorSupport() {
public void setAsText(String text) throws java.lang.IllegalArgumentException {
// Trim all whitespace
String content = StringUtils.trimAllWhitespace(text);
if (!StringUtils.hasText(content)) { // No content , ignore directly
return;
}
// replace "=" to ","
content = StringUtils.replace(content, "=", ",");
// replace ":" to ","
content = StringUtils.replace(content, ":", ",");
// String[] to Map
Map<String, String> parameters = CollectionUtils.toStringMap(commaDelimitedListToStringArray(content));
setValue(parameters);
}
});
// Bind annotation attributes
// 将注解的属性,设置到 reference 中
dataBinder.bind(new AnnotationPropertyValuesAdapter(reference, applicationContext.getEnvironment(), IGNORE_FIELD_NAMES));
}
protected String resolveModuleConfigBeanName(Reference annotation) {
return annotation.module();
}
protected String resolveApplicationConfigBeanName(Reference annotation) {
return annotation.application();
}
protected String[] resolveRegistryConfigBeanNames(Reference annotation) {
return annotation.registry();
}
protected String resolveMonitorConfigBeanName(Reference annotation) {
return annotation.monitor();
}
protected void postConfigureBean(Reference annotation, ReferenceBean bean) throws Exception {
// 设置 applicationContext
bean.setApplicationContext(applicationContext);
// 配置 interfaceClass
configureInterface(annotation, bean);
// 配置 ConsumerConfig
configureConsumerConfig(annotation, bean);
// 执行 Bean 后置属性初始化
bean.afterPropertiesSet();
}
"Duplicates") (
private void configureInterface(Reference reference, ReferenceBean referenceBean) {
// 首先,从 @Reference 获得 interfaceName 属性,从而获得 interfaceClass 类
Class<?> interfaceClass = reference.interfaceClass();
if (void.class.equals(interfaceClass)) {
interfaceClass = null;
String interfaceClassName = reference.interfaceName();
if (StringUtils.hasText(interfaceClassName)) {
if (ClassUtils.isPresent(interfaceClassName, classLoader)) {
interfaceClass = ClassUtils.resolveClassName(interfaceClassName, classLoader);
}
}
}
// 如果获得不到,则使用 interfaceClass 即可
if (interfaceClass == null) {
interfaceClass = this.interfaceClass;
}
Assert.isTrue(interfaceClass.isInterface(), "The class of field or method that was annotated @Reference is not an interface!");
referenceBean.setInterface(interfaceClass);
}
private void configureConsumerConfig(Reference reference, ReferenceBean<?> referenceBean) {
// 获得 ConsumerConfig 对象
String consumerBeanName = reference.consumer();
ConsumerConfig consumerConfig = getOptionalBean(applicationContext, consumerBeanName, ConsumerConfig.class);
// 设置到 referenceBean 中
referenceBean.setConsumer(consumerConfig);
}- ~
😈 写的相对简略。胖友注意看每一个的注释哈~
5.3.5 destroy
实现 #destroy()
方法,执行销毁逻辑。代码如下:
// ReferenceAnnotationBeanPostProcessor.java |
666. 彩蛋
比想象中的长特别特别特别多~这个还是有一些地方写的比较简略的。
本文的源码解析,对应仓库为 https://github.com/YunaiV/dubbo/tree/master-2.7.1 。
熬夜快乐~