在 Dubbo 提供的几种方式中,注解配置慢慢变成大家最常用的方式。
如果胖友不熟悉,可以查看如下文档:
我们来看看 dubbo-demo-annotation
项目下的 dubbo-demo-annotation-provider
子项目提供的 Dubbo Provider 示例。代码如下:
// Application.java public class Application { /** * In order to make sure multicast registry works, need to specify '-Djava.net.preferIPv4Stack=true' before * launch the application */ public static void main(String[] args) throws Exception { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class); context.start(); System.in.read(); } @Configuration @EnableDubbo(scanBasePackages = "org.apache.dubbo.demo.provider") // <1> @PropertySource("classpath:/spring/dubbo-provider.properties") // <2> static class ProviderConfiguration { @Bean // <3> public RegistryConfig registryConfig() { RegistryConfig registryConfig = new RegistryConfig(); registryConfig.setAddress("multicast://224.5.6.7:1234"); return registryConfig; } } } |
<1>
处,使用 @EnableDubbo
注解,配置扫描 "org.apache.dubbo.demo.provider"
目录下的 @Service
和 @Reference
Bean 对象。<2>
处,使用 @PropertySource
注解,导入 "classpath:/spring/dubbo-provider.properties"
配置文件。<3>
处,通过 @Bean
注解方法,创建 RegistryConfig Bean 对象,即注册中心。下面,我们就来看看具体的源码落。本文涉及的类,主要如下图所示:
org.apache.dubbo.config.spring.context.annotation.@EnableDubbo
注解,是 @EnableDubboConfig
和 @DubboComponentScan
的组合注解,使用时更加便利。代码如下:
// EnableDubbo.java /** * Enables Dubbo components as Spring Beans, equals * {@link DubboComponentScan} and {@link EnableDubboConfig} combination. * |
通过
@EnableDubbo
可以在指定的包名下(通过scanBasePackages
属性),或者指定的类中(通过scanBasePackageClasses
属性)扫描 Dubbo 的服务提供者(以@Service
注解)以及 Dubbo 的服务消费者(以@Reference
注解)。扫描到 Dubbo 的服务提供方和消费者之后,对其做相应的组装并初始化,并最终完成服务暴露或者引用的工作。
org.apache.dubbo.config.spring.context.annotation.@EnableDubboConfig
注解,开启 Dubbo 配置。代码如下:
// EnableDubboConfig.java /** * As a convenient and multiple {@link EnableDubboConfigBinding} * in default behavior , is equal to single bean bindings with below convention prefixes of properties: *
* In contrast, on multiple bean bindings that requires to set {@link #multiple()} to be
false
* @revised 2.5.9
*/
boolean multiple() default false;
}
|
multiple
属性,可能第一眼会有点懵逼,那咋整呢?
@EnableDubboConfig
》 对 @EnableDubboConfig
注解的介绍。@Import(DubboConfigConfigurationRegistrar.class)
注解,表明使用 DubboConfigConfigurationRegistrar 类进行导入。详细的,我们继续来看 「4.1 DubboConfigConfigurationRegistrar」 。org.apache.dubbo.config.spring.context.annotation.DubboConfigConfigurationRegistrar
,实现 ImportBeanDefinitionRegistrar 接口,处理 @EnableDubboConfig
注解,注册相应的 DubboConfigConfiguration 到 Spring 容器中。代码如下:
// DubboConfigConfigurationRegistrar.java /** * Dubbo {@link AbstractConfig Config} {@link ImportBeanDefinitionRegistrar register}, which order can be configured * * @see EnableDubboConfig * @see DubboConfigConfiguration * @see Ordered * @since 2.5.8 */ public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // 获得 @EnableDubboConfig 注解的属性 AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName())); // 获得 multiple 属性 boolean multiple = attributes.getBoolean("multiple"); // 如果为 true ,则注册 DubboConfigConfiguration.Multiple Bean 对象 if (multiple) { AnnotatedBeanDefinitionRegistryUtils.registerBeans(registry, DubboConfigConfiguration.Multiple.class); // 如果为 false ,则注册 DubboConfigConfiguration.Single Bean 对象 } else { AnnotatedBeanDefinitionRegistryUtils.registerBeans(registry, DubboConfigConfiguration.Single.class); } } } // AnnotatedBeanDefinitionRegistryUtils.java public static void registerBeans(BeanDefinitionRegistry registry, Class>... annotatedClasses) { if (ObjectUtils.isEmpty(annotatedClasses)) { return; } boolean debugEnabled = logger.isDebugEnabled(); // 创建 AnnotatedBeanDefinitionReader 对象 AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(registry); if (debugEnabled) { logger.debug(registry.getClass().getSimpleName() + " will register annotated classes : " + Arrays.asList(annotatedClasses) + " ."); } // 注册 reader.register(annotatedClasses); } |
@EnableDubboConfig
注解上的 multiple
属性的不同,创建 DubboConfigConfiguration.Multiple 或 DubboConfigConfiguration.Single 对象,注册到 Spring 容器中。org.apache.dubbo.config.spring.beans.factory.annotation.DubboConfigConfiguration
,Dubbo AbstractConfig 配置类。代码如下:
// DubboConfigConfiguration.java /** * Dubbo {@link AbstractConfig Config} {@link Configuration} * * @see Configuration * @see EnableDubboConfigBindings * @see EnableDubboConfigBinding * @see ApplicationConfig * @see ModuleConfig * @see RegistryConfig * @see ProtocolConfig * @see MonitorConfig * @see ProviderConfig * @see ConsumerConfig * @see org.apache.dubbo.config.ConfigCenterConfig * @since 2.5.8 */ public class DubboConfigConfiguration { /** * Single Dubbo {@link AbstractConfig Config} Bean Binding */ @EnableDubboConfigBindings({ @EnableDubboConfigBinding(prefix = "dubbo.application", type = ApplicationConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.module", type = ModuleConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.registry", type = RegistryConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.protocol", type = ProtocolConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.monitor", type = MonitorConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.provider", type = ProviderConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.consumer", type = ConsumerConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.config-center", type = ConfigCenterBean.class), @EnableDubboConfigBinding(prefix = "dubbo.metadata-report", type = MetadataReportConfig.class) }) public static class Single { } /** * Multiple Dubbo {@link AbstractConfig Config} Bean Binding */ @EnableDubboConfigBindings({ @EnableDubboConfigBinding(prefix = "dubbo.applications", type = ApplicationConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.modules", type = ModuleConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.registries", type = RegistryConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.protocols", type = ProtocolConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.monitors", type = MonitorConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.providers", type = ProviderConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.consumers", type = ConsumerConfig.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.config-centers", type = ConfigCenterBean.class, multiple = true), @EnableDubboConfigBinding(prefix = "dubbo.metadata-reports", type = MetadataReportConfig.class, multiple = true) }) public static class Multiple { } } |
@@EnableDubboConfigBindings
和 @EnableDubboConfigBinding
注解。
prefix
都是单数。prefix
都是复数,且有 multiple = true
。org.apache.dubbo.config.spring.context.annotation.@EnableDubboConfigBindings
注解,是 @EnableDubboConfigBinding
注解的数组。代码如下:
// EnableDubboConfigBindings.java /** * Multiple {@link EnableDubboConfigBinding} {@link Annotation} * * @since 2.5.8 * @see EnableDubboConfigBinding */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(DubboConfigBindingsRegistrar.class) public @interface EnableDubboConfigBindings { /** * The value of {@link EnableDubboConfigBindings} * * @return non-null */ EnableDubboConfigBinding[] value(); } |
@Import(DubboConfigBindingsRegistrar.class)
注解,表明使用 DubboConfigBindingsRegistrar 类进行导入。详细的,我们继续来看 「4.3.1 DubboConfigBindingsRegistrar」 。org.apache.dubbo.config.spring.context.annotation.DubboConfigBindingsRegistrar
,实现 ImportBeanDefinitionRegistrar、EnvironmentAware 接口,处理 @EnableDubboConfigBindings
注解,注册相应的 Dubbo AbstractConfig 到 Spring 容器中。代码如下:
// DubboConfigBindingsRegistrar.java /** * {@link AbstractConfig Dubbo Config} binding Bean registrar for {@link EnableDubboConfigBindings} * * @see EnableDubboConfigBindings * @see DubboConfigBindingRegistrar * @since 2.5.8 */ public class DubboConfigBindingsRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware { private ConfigurableEnvironment environment; @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // <1.1> 获得 @EnableDubboConfigBindings 注解 AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(EnableDubboConfigBindings.class.getName())); // <1.2> 获得内部的 @EnableDubboConfigBinding 注解的数组 AnnotationAttributes[] annotationAttributes = attributes.getAnnotationArray("value"); // <2> 创建 DubboConfigBindingRegistrar 对象,并设置 environment 属性 DubboConfigBindingRegistrar registrar = new DubboConfigBindingRegistrar(); registrar.setEnvironment(environment); // <3> 遍历 annotationAttributes 数组,使用 registrar 进行逐个 @EnableDubboConfigBinding 注解的注册对应的 Bean for (AnnotationAttributes element : annotationAttributes) { registrar.registerBeanDefinitions(element, registry); } } @Override public void setEnvironment(Environment environment) { Assert.isInstanceOf(ConfigurableEnvironment.class, environment); this.environment = (ConfigurableEnvironment) environment; } } |
<1.1>
、<1.2>
处,获得 @EnableDubboConfigBindings
注解,从而后面获得内部的 @EnableDubboConfigBinding
注解的数组。<2>
处,创建 DubboConfigBindingRegistrar 对象,并设置 environment
属性。<3>
处,遍历 annotationAttributes
数组,使用 registrar
,调用 DubboConfigBindingRegistrar#registerBeanDefinitions(AnnotationAttributes attributes, BeanDefinitionRegistry registry)
方法,进行逐个 @EnableDubboConfigBinding
注解的注册对应的 Bean 。EnableDubboConfigBinding
注解。org.apache.dubbo.config.spring.context.annotation.@EnableDubboConfigBinding
注解,代码如下:
// EnableDubboConfigBinding.java
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(EnableDubboConfigBindings.class)
@Import(DubboConfigBindingRegistrar.class)
public @interface EnableDubboConfigBinding {
/**
* The name prefix of the properties that are valid to bind to {@link AbstractConfig Dubbo Config}.
*
* 配置前缀
*
* @return the name prefix of the properties to bind
*/
String prefix();
/**
* 配置类
*
* @return The binding type of {@link AbstractConfig Dubbo Config}.
* @see AbstractConfig
* @see ApplicationConfig
* @see ModuleConfig
* @see RegistryConfig
*/
Class extends AbstractConfig> type();
/**
* 是否 multiple
*
* It indicates whether {@link #prefix()} binding to multiple Spring Beans.
*
* @return the default value is |
@Import(DubboConfigBindingRegistrar.class)
注解,表明使用 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 @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { // <1> 获得 @EnableDubboConfigBinding 注解 AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(EnableDubboConfigBinding.class.getName())); // <2> 注册配置对应的 Bean Definition 对象 registerBeanDefinitions(attributes, registry); } protected void registerBeanDefinitions(AnnotationAttributes attributes, BeanDefinitionRegistry registry) { // <2.1> 获得 prefix 属性 String prefix = environment.resolvePlaceholders(attributes.getString("prefix")); // 因为,有可能有占位符,所以要解析。 // <2.2> 获得 type 属性,即 AbstractConfig 的实现类 Class extends AbstractConfig> configClass = attributes.getClass("type"); // <2.3> 获得 multiple 属性 boolean multiple = attributes.getBoolean("multiple"); // <2.4> 注册 Dubbo Config Bean 对象 registerDubboConfigBeans(prefix, configClass, multiple, registry); } |
<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 private void registerDubboConfigBeans(String prefix, Class extends AbstractConfig> configClass, boolean multiple, BeanDefinitionRegistry registry) { // <1.1> 获得 prefix 开头的配置属性 Map |
<1.1>
处,调用 PropertySourcesUtils#getSubProperties(Iterable> propertySources, String prefix)
方法,获得 prefix
开头的配置属性。因为,后续会用这个属性,设置到创建的 Bean 对象中。<1.2>
处,如果配置属性为空,则无需创建。<2>
处,根据 multiple
的值,调用不同的方法,获得配置属性对应的 Bean 名字的集合。代码如下:
// DubboConfigBindingRegistrar.java // 例如:dubbo.application.${beanName}.name=dubbo-demo-annotation-provider private Set |
#resolveMultipleBeanNames(Map
方法,可能比较难理解一点。胖友可以增加如下到配置文件中:
# 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."); } } |
<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."); } } |
至此,我们发现,需要继续挖掘,让我们继续来看 「DubboConfigBindingBeanPostProcessor」 类。
org.apache.dubbo.config.spring.beans.factory.annotation.DubboConfigBindingBeanPostProcessor
,实现 BeanPostProcessor、ApplicationContextAware、InitializingBean 接口,处理 Dubbo AbstractConfig Bean 的配置属性注入。
// 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; } |
builder.addConstructorArgValue(actualPrefix).addConstructorArgValue(beanName);
一段的代码。#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; } |
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. * |
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 |
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 |
在 《Dubbo 源码分析 —— 集成 Spring Boot》 中,我们可以看到另外一个 AbstractDubboConfigBinder 的实现类 RelaxedDubboConfigBinder ,它是基于 Spring Boot Binder 进行实现。 因为艿艿没有深入了解过 Spring Boot Binder 相关,所以还说不出和 Spring DataBinder 的区别在哪。orz
实现 #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 对象的创建和属性设置,已经完成。如果胖友还是有点懵逼,可以调试一次,没有什么复杂逻辑哟。
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. * |
@Import(DubboComponentScanRegistrar.class)
注解,表明使用 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 |
<1>
处,调用 #getPackagesToScan(AnnotationMetadata metadata)
方法,获得要扫描的包。代码如下:
// DubboComponentScanRegistrar.java private Set |
<2>
处,调用 #registerServiceAnnotationBeanPostProcessor(Set
方法,创建 ServiceAnnotationBeanPostProcessor Bean 对象,后续扫描 @Service
注解的类,创建对应的 Service Bean 对象。代码如下:
// DubboComponentScanRegistrar.java private void registerServiceAnnotationBeanPostProcessor(Set |
<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); } } |
org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationBeanPostProcessor
,实现 BeanDefinitionRegistryPostProcessor、EnvironmentAware、ResourceLoaderAware、BeanClassLoaderAware 接口,扫描 @Service
注解的类,创建对应的 Spring BeanDefinition 对象,从而创建 Dubbo Service Bean 对象。
// ServiceAnnotationBeanPostProcessor.java /** * 要扫描的包的集合 */ private final Set |
实现 #postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
方法,扫描 @Service
注解的类,创建对应的 Spring BeanDefinition 对象,从而创建 Dubbo Service Bean 对象。代码如下:
// ServiceAnnotationBeanPostProcessor.java @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { // <1> 解析 packagesToScan 集合。因为,可能存在占位符 Set |
<1>
处,调用 #resolvePackagesToScan(Set
方法,解析 packagesToScan
集合。因为,可能存在占位符。代码如下:
// ServiceAnnotationBeanPostProcessor.java private Set |
<2>
处,调用 #registerServiceBeans(Set
方法,扫描 packagesToScan
包,创建对应的 Spring BeanDefinition 对象,从而创建 Dubbo Service Bean 对象。详细解析,见 「5.2.3 resolvePackagesToScan」 中。
#registerServiceBeans(Set
方法,扫描 packagesToScan
包,创建对应的 Spring BeanDefinition 对象,从而创建 Dubbo Service Bean 对象。代码如下:
// ServiceAnnotationBeanPostProcessor.java private void registerServiceBeans(Set |
<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 */ @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」 中。#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 |
#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); } |
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); } } } // |
处,从被注解的类上获得其实现的首个接口。<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
中。也就是说,注解上的属性,自然的能够设置到后续创建的 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
。若不存在,则进行注册。
整个逻辑,有点长长滴。胖友辛苦上下滑动,在瞅瞅。
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 的抽象实现类,用于支持使用自定义注解,注入对象的属性。
@Reference
注解的属性注入。相对来说,本节的 ReferenceAnnotationBeanPostProcessor ,会比上一节的 ServiceAnnotationBeanPostProcessor 复杂蛮多~ SO ,保持耐心哈。
// 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 |
实现 #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()); // 这里,貌似重复解析占位符了。不过没啥影响~ } |
<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; } |
<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 服务是远程的还是本地的,做不同的处理。为什么呢?
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
。实现 #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) { } |
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(); } } |
org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceBeanBuilder
,继承 AbstractAnnotationConfigBeanBuilder 抽象类,ReferenceBean 的构建器。
考虑到 ReferenceBeanBuilder 类,就是
#build()
方法,我们就直接结合 AbstractAnnotationConfigBeanBuilder 抽象类,一起写了。
5.3.4.1 构造方法
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 |
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 |
写的相对简略。胖友注意看每一个的注释哈~
实现 #destroy()
方法,执行销毁逻辑。代码如下:
// ReferenceAnnotationBeanPostProcessor.java @Override public void destroy() throws Exception { // 父类销毁 super.destroy(); // 清空缓存 this.referenceBeanCache.clear(); this.localReferenceBeanInvocationHandlerCache.clear(); this.injectedFieldReferenceBeanCache.clear(); this.injectedMethodReferenceBeanCache.clear(); } |