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>` 中。
- `<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
/**
* The prefix of Configuration Properties
*
* 配置属性的前缀
*/
private final String prefix;
/**
* Binding Bean Name
*
* Bean 的名字
*/
private final String beanName;
private DubboConfigBinder dubboConfigBinder;
private ApplicationContext applicationContext;
/**
* 是否忽略位置的属性
*/
private boolean ignoreUnknownFields = true;
/**
* 是否忽略类型不对的属性
*/
private boolean ignoreInvalidFields = true;
/**
* @param prefix the prefix of Configuration Properties
* @param beanName the binding Bean Name
*/
public DubboConfigBindingBeanPostProcessor(String prefix, String beanName) {
Assert.notNull(prefix, "The prefix of Configuration Properties must not be null");
Assert.notNull(beanName, "The name of bean must not be null");
this.prefix = prefix;
this.beanName = beanName;
}
```
- 所以,我们在上文中会看到,创建 DubboConfigBindingBeanPostProcessor Bean 时,会有 `builder.addConstructorArgValue(actualPrefix).addConstructorArgValue(beanName);` 一段的代码。
#### 4.5.2 afterPropertiesSet
`#afterPropertiesSet()` 方法,设置 `dubboConfigBinder` 属性。代码如下:
```
// DubboConfigBindingBeanPostProcessor.java
@Override
public void afterPropertiesSet() throws Exception {
// 获得(创建)DubboConfigBinder 对象
if (dubboConfigBinder == null) {
try {
dubboConfigBinder = applicationContext.getBean(DubboConfigBinder.class);
} catch (BeansException ignored) {
if (log.isDebugEnabled()) {
log.debug("DubboConfigBinder Bean can't be found in ApplicationContext.");
}
// Use Default implementation
dubboConfigBinder = createDubboConfigBinder(applicationContext.getEnvironment());
}
}
// 设置 ignoreUnknownFields、ignoreInvalidFields 属性
dubboConfigBinder.setIgnoreUnknownFields(ignoreUnknownFields);
dubboConfigBinder.setIgnoreInvalidFields(ignoreInvalidFields);
}
/**
* Create {@link DubboConfigBinder} instance.
*
* @param environment
* @return {@link DefaultDubboConfigBinder}
*/
protected DubboConfigBinder createDubboConfigBinder(Environment environment) {
// 创建 DefaultDubboConfigBinder 对象
DefaultDubboConfigBinder defaultDubboConfigBinder = new DefaultDubboConfigBinder();
// 设置 environment 属性
defaultDubboConfigBinder.setEnvironment(environment);
return defaultDubboConfigBinder;
}
```
- 关于 DefaultDubboConfigBinder 类,我们在下面的小节先来瞅瞅。
##### 4.5.2.1 DubboConfigBinder
`org.apache.dubbo.config.spring.context.properties.DubboConfigBinder` ,继承 EnvironmentAware 接口,Dubbo Config Binder 接口。代码如下:
```
// DubboConfigBinder.java
/**
* {@link AbstractConfig DubboConfig} Binder
*
* @see AbstractConfig
* @see EnvironmentAware
* @since 2.5.11
*/
public interface DubboConfigBinder extends EnvironmentAware {
/**
* Set whether to ignore unknown fields, that is, whether to ignore bind
* parameters that do not have corresponding fields in the target object.
* Default is "true". Turn this off to enforce that all bind parameters
* must have a matching field in the target object.
*
* @see #bind
*/
void setIgnoreUnknownFields(boolean ignoreUnknownFields);
/**
* Set whether to ignore invalid fields, that is, whether to ignore bind
* parameters that have corresponding fields in the target object which are
* not accessible (for example because of null values in the nested path).
*
Default is "false".
*
* @see #bind
*/
void setIgnoreInvalidFields(boolean ignoreInvalidFields);
/**
* Bind the properties to Dubbo Config Object under specified prefix.
*
* @param prefix
* @param dubboConfig
*/
void bind(String prefix, C dubboConfig);
}
```
- 后续的实现,我们会看到基于 Spring DataBinder 来实现。不了解 DataBinder 的胖友,可以看看 [《Spring 验证、数据绑定和类型转换》](https://my.oschina.net/u/2453016/blog/1512184) 文章。
##### 4.5.2.2 DubboConfigBinder
`org.apache.dubbo.config.spring.context.properties.AbstractDubboConfigBinder` ,实现 DubboConfigBinder 接口,DubboConfigBinder 的抽象基类。代码如下:
```
// AbstractDubboConfigBinder.java
public abstract class AbstractDubboConfigBinder implements DubboConfigBinder {
/**
* PropertySource 数组(迭代)
*/
private Iterable> propertySources;
private boolean ignoreUnknownFields = true;
private boolean ignoreInvalidFields = false;
/**
* Get multiple {@link PropertySource propertySources}
*
* @return multiple {@link PropertySource propertySources}
*/
protected Iterable> getPropertySources() {
return propertySources;
}
public boolean isIgnoreUnknownFields() {
return ignoreUnknownFields;
}
@Override
public void setIgnoreUnknownFields(boolean ignoreUnknownFields) {
this.ignoreUnknownFields = ignoreUnknownFields;
}
public boolean isIgnoreInvalidFields() {
return ignoreInvalidFields;
}
@Override
public void setIgnoreInvalidFields(boolean ignoreInvalidFields) {
this.ignoreInvalidFields = ignoreInvalidFields;
}
@Override
public final void setEnvironment(Environment environment) {
if (environment instanceof ConfigurableEnvironment) {
this.propertySources = ((ConfigurableEnvironment) environment).getPropertySources();
}
}
}
```
- 提供默认的属性。
##### 4.5.2.3 DefaultDubboConfigBinder
`org.apache.dubbo.config.spring.context.properties.DefaultDubboConfigBinder` ,继承 AbstractDubboConfigBinder 抽象类,使用 Spring DataBinder ,将配置属性设置到 Dubbo Config 对象中。代码如下:
```
// DefaultDubboConfigBinder.java
/**
* Default {@link DubboConfigBinder} implementation based on Spring {@link DataBinder}
*/
public class DefaultDubboConfigBinder extends AbstractDubboConfigBinder {
@Override
public void bind(String prefix, C dubboConfig) {
// 将 dubboConfig 包装成 DataBinder 对象
DataBinder dataBinder = new DataBinder(dubboConfig);
// Set ignored*
// 设置响应的 ignored* 属性
dataBinder.setIgnoreInvalidFields(isIgnoreInvalidFields());
dataBinder.setIgnoreUnknownFields(isIgnoreUnknownFields());
// Get properties under specified prefix from PropertySources
// 获得 prefix 开头的配置属性
Map properties = PropertySourcesUtils.getSubProperties(getPropertySources(), prefix);
// Convert Map to MutablePropertyValues
// 创建 MutablePropertyValues 对象
MutablePropertyValues propertyValues = new MutablePropertyValues(properties);
// Bind
// 绑定配置属性到 dubboConfig 中
dataBinder.bind(propertyValues);
}
}
```
- 比较简单,胖友自己瞅一眼代码即可。
在 [《Dubbo 源码分析 —— 集成 Spring Boot》](http://www.iocoder.cn/Dubbo/spring-boot-integration/) 中,我们可以看到另外一个 AbstractDubboConfigBinder 的实现类 RelaxedDubboConfigBinder ,它是基于 Spring Boot [Binder](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/context/properties/bind/Binder.html) 进行实现。😈 因为艿艿没有深入了解过 Spring Boot Binder 相关,所以还说不出和 Spring DataBinder 的区别在哪。orz
#### 4.5.3 postProcessBeforeInitialization
实现 `#postProcessBeforeInitialization(Object bean, String beanName)` 方法,设置配置属性到 Dubbo Config 中。代码如下:
```
// DubboConfigBindingBeanPostProcessor.java
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 判断必须是 beanName ,并且是 AbstractConfig 类型
if (beanName.equals(this.beanName) && bean instanceof AbstractConfig) {
AbstractConfig dubboConfig = (AbstractConfig) bean;
// 设置属性到 dubboConfig 中
dubboConfigBinder.bind(prefix, dubboConfig);
if (log.isInfoEnabled()) {
log.info("The properties of bean [name : " + beanName + "] have been binding by prefix of " + "configuration properties : " + prefix);
}
}
return bean;
}
```
至此,Dubbo Config 对象的创建和属性设置,已经完成。如果胖友还是有点懵逼,可以调试一次,没有什么复杂逻辑哟。
## 5. @DubboComponentScan
`org.apache.dubbo.config.spring.context.annotation.@DubboComponentScan` 注解,配置要扫描 `@Service` 和 `@Reference` 注解的包或者类们,从而创建对应的 Bean 对象。代码如下:
```
// DubboComponentScan.java
/**
* Dubbo Component Scan {@link Annotation},scans the classpath for annotated components that will be auto-registered as
* Spring beans. Dubbo-provided {@link Service} and {@link Reference}.
*
* @see Service
* @see Reference
* @since 2.5.7
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DubboComponentScanRegistrar.class)
public @interface DubboComponentScan {
/**
* 和 {@link #basePackages()} 等价
*
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
* declarations e.g.: {@code @DubboComponentScan("org.my.pkg")} instead of
* {@code @DubboComponentScan(basePackages="org.my.pkg")}.
*
* @return the base packages to scan
*/
String[] value() default {};
/**
* 要扫描的包的数组
*
* Base packages to scan for annotated @Service classes. {@link #value()} is an
* alias for (and mutually exclusive with) this attribute.
*
* Use {@link #basePackageClasses()} for a type-safe alternative to String-based
* package names.
*
* @return the base packages to scan
*/
String[] basePackages() default {};
/**
* 要扫描的类的数组
*
* Type-safe alternative to {@link #basePackages()} for specifying the packages to
* scan for annotated @Service classes. The package of each class specified will be
* scanned.
*
* @return classes from the base packages to scan
*/
Class>[] basePackageClasses() default {};
}
```
- `@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
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// <1> 获得要扫描的包
Set packagesToScan = getPackagesToScan(importingClassMetadata);
// <2> 创建 ServiceAnnotationBeanPostProcessor Bean 对象,后续扫描 `@Service` 注解的类,创建对应的 Service Bean 对象
registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);
// <3> 创建 ReferenceAnnotationBeanPostProcessor Bean 对象,后续扫描 `@Reference` 注解的类,创建对应的 Reference Bean 对象
registerReferenceAnnotationBeanPostProcessor(registry);
}
// ... 省略稍后调用的方法。
```
- `<1>` 处,调用 `#getPackagesToScan(AnnotationMetadata metadata)` 方法,获得要扫描的包。代码如下:
```
// DubboComponentScanRegistrar.java
private Set 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 packagesToScan = new LinkedHashSet(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 packagesToScan, BeanDefinitionRegistry registry)` 方法,创建 ServiceAnnotationBeanPostProcessor Bean 对象,后续扫描 `@Service` 注解的类,创建对应的 Service Bean 对象。代码如下:
```
// DubboComponentScanRegistrar.java
private void registerServiceAnnotationBeanPostProcessor(Set 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
/**
* 要扫描的包的集合
*/
private final Set packagesToScan;
private Environment environment;
private ResourceLoader resourceLoader;
private ClassLoader classLoader;
public ServiceAnnotationBeanPostProcessor(String... packagesToScan) { // 上述文章使用到的构造方法
this(Arrays.asList(packagesToScan));
}
public ServiceAnnotationBeanPostProcessor(Collection packagesToScan) {
this(new LinkedHashSet(packagesToScan));
}
public ServiceAnnotationBeanPostProcessor(Set packagesToScan) {
this.packagesToScan = packagesToScan;
}
```
#### 5.2.2 postProcessBeanDefinitionRegistry
实现 `#postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)` 方法,扫描 `@Service` 注解的类,创建对应的 Spring BeanDefinition 对象,从而创建 Dubbo Service Bean 对象。代码如下:
```
// ServiceAnnotationBeanPostProcessor.java
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// <1> 解析 packagesToScan 集合。因为,可能存在占位符
Set resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
// <2> 扫描 packagesToScan 包,创建对应的 Spring BeanDefinition 对象,从而创建 Dubbo Service Bean 对象。
if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
registerServiceBeans(resolvedPackagesToScan, registry);
} else {
if (logger.isWarnEnabled()) {
logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
}
}
}
```
- `<1>` 处,调用 `#resolvePackagesToScan(Set packagesToScan)` 方法,解析 `packagesToScan` 集合。因为,可能存在占位符。代码如下:
```
// ServiceAnnotationBeanPostProcessor.java
private Set resolvePackagesToScan(Set packagesToScan) {
Set resolvedPackagesToScan = new LinkedHashSet(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 packagesToScan, BeanDefinitionRegistry registry)` 方法,扫描 `packagesToScan` 包,创建对应的 Spring BeanDefinition 对象,从而创建 Dubbo Service Bean 对象。详细解析,见 「5.2.3 resolvePackagesToScan」中。
#### 5.2.3 resolvePackagesToScan
`#registerServiceBeans(Set packagesToScan, BeanDefinitionRegistry registry)` 方法,扫描 `packagesToScan` 包,创建对应的 Spring BeanDefinition 对象,从而创建 Dubbo Service Bean 对象。代码如下:
```
// ServiceAnnotationBeanPostProcessor.java
private void registerServiceBeans(Set packagesToScan, BeanDefinitionRegistry registry) {
// <1.1> 创建 DubboClassPathBeanDefinitionScanner 对象
DubboClassPathBeanDefinitionScanner scanner = new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
// <1.2> 获得 BeanNameGenerator 对象,并设置 beanNameGenerator 到 scanner 中
BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
scanner.setBeanNameGenerator(beanNameGenerator);
// <1.3> 设置过滤获得带有 @Service 注解的类
scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class));
// <2> 遍历 packagesToScan 数组
for (String packageToScan : packagesToScan) {
// Registers @Service Bean first
// <2.1> 执行扫描
scanner.scan(packageToScan);
// Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not.
// <2.2> 创建每个在 packageToScan 扫描到的类,对应的 BeanDefinitionHolder 对象,返回 BeanDefinitionHolder 集合
Set beanDefinitionHolders = findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);
// <2.3> 注册到 registry 中
if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
registerServiceBean(beanDefinitionHolder, registry, scanner);
}
if (logger.isInfoEnabled()) {
logger.info(beanDefinitionHolders.size() + " annotated Dubbo's @Service Components { " + beanDefinitionHolders + " } were scanned under package[" + packageToScan + "]");
}
} else {
if (logger.isWarnEnabled()) {
logger.warn("No Spring Bean annotating Dubbo's @Service was found under package[" + packageToScan + "]");
}
}
}
}
```
- `<1.1>` 处,创建 DubboClassPathBeanDefinitionScanner 对象。它是用于扫描指定包下符合条件的类,用于将每个符合条件的类,创建对应的 BeanDefinition 对象,从而创建 Bean 。关于 DubboClassPathBeanDefinitionScanner 类,胖友点击 [链接](https://github.com/apache/incubator-dubbo/blob/master/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java) 瞅一眼即可。
- `<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
*/
@SuppressWarnings("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
/**
* Finds a {@link Set} of {@link BeanDefinitionHolder BeanDefinitionHolders} whose bean type annotated
* {@link Service} Annotation.
*
* @param scanner {@link ClassPathBeanDefinitionScanner}
* @param packageToScan pachage to scan
* @param registry {@link BeanDefinitionRegistry}
* @return non-null
* @since 2.5.8
*/
@SuppressWarnings("Duplicates")
private Set findServiceBeanDefinitionHolders(
ClassPathBeanDefinitionScanner scanner, String packageToScan, BeanDefinitionRegistry registry,
BeanNameGenerator beanNameGenerator) {
// 获得 packageToScan 包下符合条件的 BeanDefinition 集合
Set beanDefinitions = scanner.findCandidateComponents(packageToScan);
// 创建 BeanDefinitionHolder 集合
Set beanDefinitionHolders = new LinkedHashSet(beanDefinitions.size());
// 遍历 beanDefinitions 数组
for (BeanDefinition beanDefinition : beanDefinitions) {
// 获得 Bean 的名字
String beanName = beanNameGenerator.generateBeanName(beanDefinition, registry);
// 创建 BeanDefinitionHolder 对象
BeanDefinitionHolder beanDefinitionHolder = new BeanDefinitionHolder(beanDefinition, beanName);
// 添加到 beanDefinitions 中
beanDefinitionHolders.add(beanDefinitionHolder);
}
return beanDefinitionHolders;
}
```
#### 5.2.5 registerServiceBean
`#registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry, DubboClassPathBeanDefinitionScanner scanner)` 方法,注册到 `registry` 中。代码如下:
```
// ServiceAnnotationBeanPostProcessor.java
/**
* Registers {@link ServiceBean} from new annotated {@link Service} {@link BeanDefinition}
*
* @param beanDefinitionHolder
* @param registry
* @param scanner
* @see ServiceBean
* @see BeanDefinition
*/
@SuppressWarnings("Duplicates")
private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
DubboClassPathBeanDefinitionScanner scanner) {
// <1.1> 解析 Bean 的类
Class> beanClass = resolveClass(beanDefinitionHolder);
// <1.2> 获得 @Service 注解
Service service = AnnotationUtils.findAnnotation(beanClass, Service.class);
// <1.3> 获得 Service 接口
Class> interfaceClass = resolveServiceInterfaceClass(beanClass, service);
// <1.4> 获得 Bean 的名字
String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
// <1.5> 创建 AbstractBeanDefinition 对象
AbstractBeanDefinition serviceBeanDefinition = buildServiceBeanDefinition(service, interfaceClass, annotatedServiceBeanName);
// ServiceBean Bean name
// <2> 重新生成 Bean 的名字
String beanName = generateServiceBeanName(service, interfaceClass, annotatedServiceBeanName);
// <3> 校验在 scanner 中,已经存在 beanName 。若不存在,则进行注册。
if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
registry.registerBeanDefinition(beanName, serviceBeanDefinition);
if (logger.isInfoEnabled()) {
logger.info("The BeanDefinition[" + serviceBeanDefinition + "] of ServiceBean has been registered with name : " + beanName);
}
} else {
if (logger.isWarnEnabled()) {
logger.warn("The Duplicated BeanDefinition[" + serviceBeanDefinition + "] of ServiceBean[ bean name : " + beanName + "] was be found , Did @DubboComponentScan scan to same package in many times?");
}
}
}
```
- `<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 类型。
- `<1.2>` 处,获得 `@Service` 注解。
- `<1.3>` 处,调用 `#resolveServiceInterfaceClass(Class> annotatedServiceBeanClass, Service service)` 方法,获得 Service 接口。代码如下:
```
// ServiceAnnotationBeanPostProcessor.java
@SuppressWarnings("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);
}
}
}
// 【一般情况下,使用这个】获得不到,则从被注解的类上获得其实现的首个接口
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;
}
```
- 虽然代码比较长,但是重点看 `` 处,从被注解的类上获得其实现的首个接口。
- `<1.4>` 处,获得 Bean 的名字。
- `<1.5>` 处,调用 `#buildServiceBeanDefinition(Service service, Class> interfaceClass, String annotatedServiceBeanName)` 方法,创建 AbstractBeanDefinition 对象。代码如下:
```
// ServiceAnnotationBeanPostProcessor.java
@SuppressWarnings("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();
// 创建 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 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 protocolRuntimeBeanReferences = toRuntimeBeanReferences(protocolConfigBeanNames);
if (!protocolRuntimeBeanReferences.isEmpty()) {
builder.addPropertyValue("protocols", protocolRuntimeBeanReferences);
}
return builder.getBeanDefinition();
}
// RuntimeBeanReference ,在解析到依赖的Bean的时侯,解析器会依据依赖bean的name创建一个RuntimeBeanReference对像,将这个对像放入BeanDefinition的MutablePropertyValues中。
// 此处,和上面不太一样的原因,因为是多个
@SuppressWarnings("Duplicates")
private ManagedList toRuntimeBeanReferences(String... beanNames) {
ManagedList runtimeBeanReferences = new ManagedList();
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);
}
```
- 比较冗长,顺着往下看即可。
- ``处,创建 AnnotationPropertyValuesAdapter 对象,添加到`propertyValues`中。此处,是将注解上的属性,设置到`propertyValues`中。也就是说,注解上的属性,自然的能够设置到后续创建的 Service Bean 的对象中。
- 举个例子,如果说 `@Service(version="1.0.0")` ,那么这个版本号(`version`),就可以设置到 Dubbo Service Bean 中去了。
- 关`org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationPropertyValuesAdapter` 类,就是上述的用途,比较简单,胖友点击 [链接](https://github.com/apache/incubator-dubbo/blob/ff0ce37c46523e9d0dfa13748fca339e68edc027/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/AnnotationPropertyValuesAdapter.java) 查看即可。
- `<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);
}
}
```
- 结果示例如下:[![`beanName`](http://static2.iocoder.cn/images/Dubbo/2018_01_22/02.jpg)](http://static2.iocoder.cn/images/Dubbo/2018_01_22/02.jpg)`beanName`
- `<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 自 类。所以呢,我们先不深究这个类,只要知道如下:
>
> - 英文:Abstract generic {@link BeanPostProcessor} implementation for customized annotation that annotated injected-object.
> - 中文:BeanPostProcessor 的抽象实现类,用于支持使用自定义注解,注入对象的属性。
- 此时,ReferenceAnnotationBeanPostProcessor 实现的就是 支持 `@Reference` 注解的属性注入。
> 相对来说,本节的 ReferenceAnnotationBeanPostProcessor ,会比上一节的 ServiceAnnotationBeanPostProcessor 复杂蛮多~ SO ,保持耐心哈。
#### 5.3.1 构造方法
```
// ReferenceAnnotationBeanPostProcessor.java
/**
* The bean name of {@link ReferenceAnnotationBeanPostProcessor}
*/
public static final String BEAN_NAME = "referenceAnnotationBeanPostProcessor";
/**
* Cache size
*/
private static final int CACHE_SIZE = Integer.getInteger(BEAN_NAME + ".cache.size", 32);
/**
* ReferenceBean 缓存 Map
*
* KEY:Reference Bean 的名字
*/
private final ConcurrentMap> referenceBeanCache = new ConcurrentHashMap>(CACHE_SIZE);
/**
* ReferenceBeanInvocationHandler 缓存 Map
*
* KEY:Reference Bean 的名字
*/
private final ConcurrentHashMap localReferenceBeanInvocationHandlerCache = new ConcurrentHashMap(CACHE_SIZE);
/**
* 使用属性进行注入的 @Reference Bean 的缓存 Map
*
* 一般情况下,使用这个
*/
private final ConcurrentMap> injectedFieldReferenceBeanCache = new ConcurrentHashMap>(CACHE_SIZE);
/**
* 使用方法进行注入的 @Reference Bean 的缓存 Map
*/
private final ConcurrentMap> injectedMethodReferenceBeanCache = new ConcurrentHashMap>(CACHE_SIZE);
private ApplicationContext applicationContext;
```
- 具体的每个变量的时候,结合下面来看。
#### 5.3.2 doGetInjectedBean
实现 `#doGetInjectedBean(Reference reference, Object bean, String beanName, Class> injectedType, InjectionMetadata.InjectedElement injectedElement)` 方法,获得要注入的 `@Reference` Bean 。代码如下:
```
// ReferenceAnnotationBeanPostProcessor.java
@Override
protected Object doGetInjectedBean(Reference reference, Object bean, String beanName, Class> injectedType,
InjectionMetadata.InjectedElement injectedElement) throws Exception {
// <1> 获得 Reference Bean 的名字
String referencedBeanName = buildReferencedBeanName(reference, injectedType);
// <2> 创建 ReferenceBean 对象
ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referencedBeanName, reference, injectedType, getClassLoader());
// <3> 缓存到 injectedFieldReferenceBeanCache or injectedMethodReferenceBeanCache 中
cacheInjectedReferenceBean(referenceBean, injectedElement);
// <4> 创建 Proxy 代理对象
return buildProxy(referencedBeanName, referenceBean, injectedType);
}
```
- `<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` or `injectedMethodReferenceBeanCache` 中。代码如下:
```
// 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);
}
// 之后,根据引用的 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;
}
```
- 比较复杂的是,``处,根据引用的 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;
}
@Override
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
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ServiceBeanExportedEvent) {
onServiceBeanExportEvent((ServiceBeanExportedEvent) event);
} else if (event instanceof ContextRefreshedEvent) {
onContextRefreshedEvent((ContextRefreshedEvent) event);
}
}
private void onServiceBeanExportEvent(ServiceBeanExportedEvent event) {
// 获得 ServiceBean 对象
ServiceBean serviceBean = event.getServiceBean();
// 初始化对应的 ReferenceBeanInvocationHandler
initReferenceBeanInvocationHandler(serviceBean);
}
private void initReferenceBeanInvocationHandler(ServiceBean serviceBean) {
String serviceBeanName = serviceBean.getBeanName();
// Remove ServiceBean when it's exported
// 从 localReferenceBeanInvocationHandlerCache 缓存中,移除
ReferenceBeanInvocationHandler handler = localReferenceBeanInvocationHandlerCache.remove(serviceBeanName);
// Initialize
// 执行初始化
if (handler != null) {
handler.init();
}
}
private void onContextRefreshedEvent(ContextRefreshedEvent event) {
}
```
- 重点在于处理 ServiceBeanExportedEvent 事件。处理时,如果判断 `localReferenceBeanInvocationHandlerCache` 中存在 ReferenceBeanInvocationHandler 对象,说明有它未初始化。后续,调用 `ReferenceBeanInvocationHandler#init()` 方法,从而完成。这块,胖友结合 「5.2.2 doGetInjectedBean」一起,是不是就明白了。
- 在 ServiceBean 暴露服务完成后,会发布 ServiceBeanExportedEvent 事件。代码如下:
```
// ServiceBean.java
private ApplicationEventPublisher applicationEventPublisher;
/**
* @since 2.6.5
*/
@Override
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
abstract class AbstractAnnotationConfigBeanBuilder {
/**
* 注解
*/
protected final A annotation;
protected final ApplicationContext applicationContext;
protected final ClassLoader classLoader;
/**
* Bean 对象
*/
protected Object bean;
/**
* 接口
*/
protected Class> interfaceClass;
protected AbstractAnnotationConfigBeanBuilder(A annotation, ClassLoader classLoader,
ApplicationContext applicationContext) {
Assert.notNull(annotation, "The Annotation must not be null!");
Assert.notNull(classLoader, "The ClassLoader must not be null!");
Assert.notNull(applicationContext, "The ApplicationContext must not be null!");
this.annotation = annotation;
this.applicationContext = applicationContext;
this.classLoader = classLoader;
}
}
// ReferenceBeanBuilder.java
class ReferenceBeanBuilder extends AbstractAnnotationConfigBeanBuilder {
private ReferenceBeanBuilder(Reference annotation, ClassLoader classLoader, ApplicationContext applicationContext) {
super(annotation, classLoader, applicationContext);
}
public static ReferenceBeanBuilder create(Reference annotation, ClassLoader classLoader, ApplicationContext applicationContext) {
return new ReferenceBeanBuilder(annotation, classLoader, applicationContext);
}
}
```
- 其中,泛型 `A` 对应 `@Reference` 注解,泛型 `B` 对应 ReferenceBean 类。
##### 5.3.4.2 build
`#build()` 方法,构造泛型 `B` 对象。此处,就是构造 ReferenceBean 对象。代码如下:
```
// AbstractAnnotationConfigBeanBuilder.java
public final B build() throws Exception {
// 校验依赖
checkDependencies();
// 执行构造 Bean 对象
B bean = doBuild();
// 配置 Bean 对象
configureBean(bean);
if (logger.isInfoEnabled()) {
logger.info("The bean[type:" + bean.getClass().getSimpleName() + "] has been built.");
}
return bean;
}
private void checkDependencies() {
}
/**
* Builds {@link B Bean}
*
* @return {@link B Bean}
*/
protected abstract B doBuild();
protected void configureBean(B bean) throws Exception {
// 前置配置
preConfigureBean(annotation, bean);
// 配置 RegistryConfig 属性
configureRegistryConfigs(bean);
// 配置 MonitorConfig 属性
configureMonitorConfig(bean);
// 配置 ApplicationConfig 属性
configureApplicationConfig(bean);
// 配置 ModuleConfig 属性
configureModuleConfig(bean);
// 后置配置
postConfigureBean(annotation, bean);
}
protected abstract void preConfigureBean(A annotation, B bean) throws Exception; // 抽象方法
private void configureRegistryConfigs(B bean) {
String[] registryConfigBeanIds = resolveRegistryConfigBeanNames(annotation);
List registryConfigs = BeanFactoryUtils.getBeans(applicationContext, registryConfigBeanIds, RegistryConfig.class);
bean.setRegistries(registryConfigs);
}
private void configureMonitorConfig(B bean) {
String monitorBeanName = resolveMonitorConfigBeanName(annotation);
MonitorConfig monitorConfig = BeanFactoryUtils.getOptionalBean(applicationContext, monitorBeanName, MonitorConfig.class);
bean.setMonitor(monitorConfig);
}
private void configureApplicationConfig(B bean) {
String applicationConfigBeanName = resolveApplicationConfigBeanName(annotation);
ApplicationConfig applicationConfig = BeanFactoryUtils.getOptionalBean(applicationContext, applicationConfigBeanName, ApplicationConfig.class);
bean.setApplication(applicationConfig);
}
private void configureModuleConfig(B bean) {
String moduleConfigBeanName = resolveModuleConfigBeanName(annotation);
ModuleConfig moduleConfig = BeanFactoryUtils.getOptionalBean(applicationContext, moduleConfigBeanName, ModuleConfig.class);
bean.setModule(moduleConfig);
}
protected abstract String resolveModuleConfigBeanName(A annotation); // 抽象方法
protected abstract String resolveApplicationConfigBeanName(A annotation); // 抽象方法
protected abstract String[] resolveRegistryConfigBeanNames(A annotation); // 抽象方法
protected abstract String resolveMonitorConfigBeanName(A annotation); // 抽象方法
protected abstract void postConfigureBean(A annotation, B bean) throws Exception; // 抽象方法
```
- ReferenceBeanBuilder 主要对上面的抽象方法,进行具体实现。代码如下:
```
// ReferenceBeanBuilder.java
static final String[] IGNORE_FIELD_NAMES = of("application", "module", "consumer", "monitor", "registry")
@Override
protected ReferenceBean doBuild() {
// 创建 ReferenceBean 对象
return new ReferenceBean<>();
}
@SuppressWarnings("Duplicates")
@Override
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() {
@Override
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 parameters = CollectionUtils.toStringMap(commaDelimitedListToStringArray(content));
setValue(parameters);
}
});
// Bind annotation attributes
// 将注解的属性,设置到 reference 中
dataBinder.bind(new AnnotationPropertyValuesAdapter(reference, applicationContext.getEnvironment(), IGNORE_FIELD_NAMES));
}
@Override
protected String resolveModuleConfigBeanName(Reference annotation) {
return annotation.module();
}
@Override
protected String resolveApplicationConfigBeanName(Reference annotation) {
return annotation.application();
}
@Override
protected String[] resolveRegistryConfigBeanNames(Reference annotation) {
return annotation.registry();
}
@Override
protected String resolveMonitorConfigBeanName(Reference annotation) {
return annotation.monitor();
}
@Override
protected void postConfigureBean(Reference annotation, ReferenceBean bean) throws Exception {
// 设置 applicationContext
bean.setApplicationContext(applicationContext);
// 配置 interfaceClass
configureInterface(annotation, bean);
// 配置 ConsumerConfig
configureConsumerConfig(annotation, bean);
// 执行 Bean 后置属性初始化
bean.afterPropertiesSet();
}
@SuppressWarnings("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
@Override
public void destroy() throws Exception {
// 父类销毁
super.destroy();
// 清空缓存
this.referenceBeanCache.clear();
this.localReferenceBeanInvocationHandlerCache.clear();
this.injectedFieldReferenceBeanCache.clear();
this.injectedMethodReferenceBeanCache.clear();
}
```