1:写在前面
在这篇文章 中我们分析了通过xml配置方式配置解析的过程,本文一起来看下基于注解配置方式,即Java config方式配置的解析过程。另外关于dubbo注解配置使用可以参考如下的文章列表:
dubbo之入门 。
dubbo之外部化配置 。
如下是服务提供者端一个可能的配置:
@Configuration
@EnableDubbo(scanBasePackages = "dongshi.daddy.service.annotation")
public class DubboConfiguration {
@Bean // #1 服务提供者信息配置
public ProviderConfig providerConfig() {
ProviderConfig providerConfig = new ProviderConfig();
providerConfig.setTimeout(1000);
return providerConfig;
}
@Bean // #2 分布式应用信息配置,相当于xml配置:<dubbo:application name="dongshidaddy-provider" owner="dongshidaddy">
public ApplicationConfig applicationConfig() {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("dubbo-annotation-provider");
return applicationConfig;
}
@Bean // #3 注册中心信息配置,相当于xml配置:<dubbo:registry address="zookeeper://192.168.10.119:2181" />
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setProtocol("zookeeper");
registryConfig.setAddress("192.168.10.119");
registryConfig.setPort(2181);
return registryConfig;
}
@Bean // #4 使用协议配置,这里使用 dubbo,相当于xml配置:<dubbo:protocol name="dubbo" port="20823"/>
public ProtocolConfig protocolConfig() {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setName("dubbo");
protocolConfig.setPort(20885);
return protocolConfig;
}
}
启动类:
public class ProviderAnnotationMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DubboConfiguration.class);
context.start();
new Thread(() -> {
while (true) {
try {
Thread.sleep(900000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
服务消费者端配置:
@Configuration
@EnableDubbo(scanBasePackages = "dongshi.daddy.service.annotation")
@ComponentScan(value = {"dongshi.daddy.service.annotation"})
public class ConsumerConfiguration {
@Bean // 应用配置
public ApplicationConfig applicationConfig() {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("dubbo-annotation-consumer");
Map<String, String> stringStringMap = new HashMap<String, String>();
stringStringMap.put("qos.enable","true");
stringStringMap.put("qos.accept.foreign.ip","false");
stringStringMap.put("qos.port","33333");
applicationConfig.setParameters(stringStringMap);
return applicationConfig;
}
@Bean // 服务消费者配置
public ConsumerConfig consumerConfig() {
ConsumerConfig consumerConfig = new ConsumerConfig();
consumerConfig.setTimeout(3000);
return consumerConfig;
}
@Bean // 配置注册中心
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setProtocol("zookeeper");
registryConfig.setAddress("192.168.10.119");
registryConfig.setPort(2181);
return registryConfig;
}
}
启动类:
public class ConsumerAnnotationMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
context.start(); // 启动
ConsumerAnnotationService consumerAnnotationService = context.getBean(ConsumerAnnotationService.class);
String hello = consumerAnnotationService.doSayHello("annotation"); // 调用方法
System.out.println("result: " + hello); // 输出结果
}
}
2. @EnableDubbo
类全限定名称是com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo
,源码如下:
@Target({ElementType.TYPE}) // 用在类上
@Retention(RetentionPolicy.RUNTIME) // 保留到运行时
@Inherited // 可以被继承
@Documented
@EnableDubboConfig
@DubboComponentScan // 启用dubbo组件的扫描,即扫描@Service注解的服务提供者类,@Reference注解的服务消费者类
public @interface EnableDubbo {
// 扫描使用了@Service,@Reference注解的类的基础包,是相当于使用DubboComponentScan.class注解的basePackages
@AliasFor(annotation = DubboComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
// 同scanBasePackages直接以字符串的方式来指定要扫描的包的集合,该值指定一组class后,会以class所在的包路径来扫描@Service和@Reference注解的类
@AliasFor(annotation = DubboComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
// 暂时不知道干啥用的
@AliasFor(annotation = EnableDubboConfig.class, attribute = "multiple")
boolean multipleConfig() default true;
}
可以看到该注解组合了注解@EnableDubboConfig
和注解DubboComponentScan
,接下来我们先来看下@EnableDubboConfig
注解。
3. @EnableDubboConfig
源码如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Import(DubboConfigConfigurationRegistrar.class)
public @interface EnableDubboConfig {
// 是否允许dubbo多配置bean绑定,2.5.8版本引入默认为false,2.5.9版本开始修改为默认true
boolean multiple() default true;
}
可以看到源码中通过@Import(DubboConfigConfigurationRegistrar.class)
引入了bean定义,因此,接下来我们看下DubboConfigConfigurationRegistrar到底做了什么操作。
3.1:DubboConfigConfigurationRegistrar
源码如下:
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");
// 2021-12-27 13:30:24
registerBeans(registry, DubboConfigConfiguration.Single.class);
// 2021-12-27 13:30:45
if (multiple) { // Since 2.6.6 https://github.com/apache/incubator-dubbo/issues/3193
registerBeans(registry, DubboConfigConfiguration.Multiple.class);
}
}
}
2021-12-27 13:30:24
处是默认注册一个DubboConfigConfiguration.Single
的内部类的bean,2021-12-27 13:30:45
处是如果是开启了多dubbo配置bean绑定则注册DubboConfigConfiguration.Multiple
内部类,可以看到都是DubboConfigConfiguration的内部类,源码如下:
public class DubboConfigConfiguration {
// 单dubbo配置bean绑定
@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)
})
public static class Single {
}
// 多dubbo配置bean绑定,注意都设置了"multiple = true"
@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)
})
public static class Multiple {
}
}
可以看到都是用了@EnableDubboConfigBindings
和@EnableDubboConfigBinding
注解,这两个注解是用来设置指定外部配置文件属性前缀绑定到AbstractConfig的子类的,下面来一起看下都完成了哪些工作。@EnableDubboConfigBindings
参考3.2:@EnableDubboConfigBindings
,@EnableDubboConfigBinding
参考3.3:@EnableDubboConfigBinding
。
3.2:@EnableDubboConfigBindings
源码如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DubboConfigBindingsRegistrar.class)
public @interface EnableDubboConfigBindings {
EnableDubboConfigBinding[] value();
}
可以看到使用了@Import(DubboConfigBindingsRegistrar.class)
来引入bean定义。
3.2.1:DubboConfigBindingsRegistrar
源码如下:
public class DubboConfigBindingsRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {
// 环境
private ConfigurableEnvironment environment;
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 获得类上标注的@EnableDubboConfigBindings属性信息
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
importingClassMetadata.getAnnotationAttributes(EnableDubboConfigBindings.class.getName()));
// 获取value值,即使用@EnableDubboConfigBinding注解配置的属性前缀和AbstractConfig子类的对应关系
AnnotationAttributes[] annotationAttributes = attributes.getAnnotationArray("value");
// 创建DubboConfigBindingRegistrar并使用其完成dubbo注册
DubboConfigBindingRegistrar registrar = new DubboConfigBindingRegistrar();
registrar.setEnvironment(environment);
for (AnnotationAttributes element : annotationAttributes) {
// 2021-12-28 13:31:38
registrar.registerBeanDefinitions(element, registry);
}
}
@Override
public void setEnvironment(Environment environment) {
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
this.environment = (ConfigurableEnvironment) environment;
}
}
2021-12-28 13:31:38
处是注册单个映射关系的bean定义,具体参考3.3.1:DubboConfigBindingRegistrar
。
3.3:@EnableDubboConfigBinding
源码如下:
// 启用外部化配置,从@PropertySource注解指定的配置文件中读取相关配置映射绑定到AbstractConfig对应的子类中,前缀比如"dubbo.application.",`dubbo.application`
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DubboConfigBindingRegistrar.class)
public @interface EnableDubboConfigBinding {
// 能够绑定到AbstractConfig子类的属性前缀
String prefix();
// 要绑定的AbstractConfig子类
Class<? extends AbstractConfig> type();
// 是否支持绑定到多个spring bean
boolean multiple() default false;
}
通过@Import(DubboConfigBindingRegistrar.class)
引入相关的spring bean,具体参考3.3.1:DubboConfigBindingRegistrar
。
3.3.1:DubboConfigBindingRegistrar
源码如下:
public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware {
private final Log log = LogFactory.getLog(getClass());
private ConfigurableEnvironment environment;
protected void registerBeanDefinitions(AnnotationAttributes attributes, BeanDefinitionRegistry registry) {
// 获取在@EnableDubboConfigBinding注解中配置的prefix值,如dubbo.application
String prefix = environment.resolvePlaceholders(attributes.getString("prefix"));
// 获取在@EnableDubboConfigBinding注解中type的值,即设置的要绑定的AbtractConfig子类
Class<? extends AbstractConfig> configClass = attributes.getClass("type");
// 获取multiple属性的值,即是否支持dubbo多配置bean绑定
boolean multiple = attributes.getBoolean("multiple");
registerDubboConfigBeans(prefix, configClass, multiple, registry);
}
private void registerDubboConfigBeans(String prefix,
Class<? extends AbstractConfig> configClass,
boolean multiple,
BeanDefinitionRegistry registry) {
// 获取配置文件中以prefix开头的配置信息,如获取dubbo.application开头的,如下配置:
/*
dubbo.application.name=dongshidaddy-provider
dubbo.application.owner=dongshidaddy
*/
// 则这里获取的结果就是:
/*
"owner" -> "dongshidaddy"
"name" -> "dongshidaddy-provider"
*/
Map<String, Object> properties = getSubProperties(environment.getPropertySources(), prefix);
// 没有对应的外部配置属性,不报错,只是给出日志,就return
if (CollectionUtils.isEmpty(properties)) {
if (log.isDebugEnabled()) {
log.debug("There is no property for binding to dubbo config class [" + configClass.getName()
+ "] within prefix [" + prefix + "]");
}
return;
}
// 2021-12-29 14:15:46
// 获取绑定的AbstractConfig的bean名称集合
Set<String> beanNames = multiple ? resolveMultipleBeanNames(properties) :
Collections.singleton(resolveSingleBeanName(properties, configClass, registry));
for (String beanName : beanNames) {
// 将bean定义注册到BeanDefinitionRegistry registry中
registerDubboConfigBean(beanName, configClass, registry);
// 2021-12-29 16:24:02
// 注册DubboConfigBindingBeanPostProcessor后置bean处理器,关于BeanPostProcessort可以参考:
//
//
registerDubboConfigBindingBeanPostProcessor(prefix, beanName, multiple, registry);
}
}
}
2021-12-29 14:15:46
处是注册bean名称,multiple=false
时resolveSingleBeanName,源码如下:
class FakeCls {
private String resolveSingleBeanName(Map<String, Object> properties, Class<? extends AbstractConfig> configClass,
BeanDefinitionRegistry registry) {
// 获取id属性,如dubbo.application.id=myApplicationConfigBean,则使用myApplicationConfigBean
String beanName = (String) properties.get("id");
// 没有配置id属性,则使用“类全限定名称+#序号”方式生成结果,如com.alibaba.dubbo.config.ApplicationConfig
// 则结果可能是com.alibaba.dubbo.config.ApplicationConfig#0
if (!StringUtils.hasText(beanName)) {
BeanDefinitionBuilder builder = rootBeanDefinition(configClass);
beanName = BeanDefinitionReaderUtils.generateBeanName(builder.getRawBeanDefinition(), registry);
}
// 返回bean名称
return beanName;
}
}
multiple=true
时resolveMultipleBeanNames源码如下:
class FakeCls {
private Set<String> resolveMultipleBeanNames(Map<String, Object> properties) {
// 以dubbo.application为例多配置bean格式为dubbo.applications.${bean名称}.${属性名称} = 属性值,比如配置如下:
/*
dubbo.applications.applicationBean.name = dubbo-demo-application
dubbo.applications.applicationBean2.name = dubbo-demo-application2
dubbo.applications.applicationBean3.name = dubbo-demo-application3
*/
// 则properties结果就是:
/*
"applicationBean.name" -> "dubbo-demo-application"
"applicationBean2.name" -> "dubbo-demo-application2"
"applicationBean3.name" -> "dubbo-demo-application3"
*/
// 其中的applicationBean,applicationBean2,applicationBean3就是就是我们需要的bean名称
Set<String> beanNames = new LinkedHashSet<String>();
for (String propertyName : properties.keySet()) {
int index = propertyName.indexOf(".");
if (index > 0) {
String beanName = propertyName.substring(0, index);
beanNames.add(beanName);
}
}
return beanNames;
}
}
2021-12-29 16:24:02
处是添加后置bean处理器,具体参考3.4:DubboConfigBindingBeanPostProcessor
,主要是完成的工作是填充配置bean的相关属性,从前面的分析我们看到只是创建了配置bean的bean定义并没有填充属性,解析来再来看下这个属性填充的过程。
3.4:DubboConfigBindingBeanPostProcessor
这是一个后置bean处理器的实现类,关于后置bean处理器可以参考这篇文章 。
3.4.1:构造方法
class FakeCls {
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");
// 外部化配置属性前缀,如dubbo.application
this.prefix = prefix;
// 外部化配置对应的AbstractConfig子类的bean名称
this.beanName = beanName;
}
}
3.4.2:afterPropertiesSet
因为实现了InitializingBean
接口所以会在DubboConfigBindingBeanPostProcessor bean创建完毕并设置属性完毕后调用afterPropertiesSet方法,主要是设置config bean的后置处理时需要的相关对象,如用来设置config bean属性的DataBinder等,源码如下:
class FakeCls {
public void afterPropertiesSet() throws Exception {
// 2021-12-30 19:29:47
initDubboConfigBinder();
// 2021-12-30 19:29:53
initConfigBeanCustomizers();
}
}
2021-12-30 19:29:47
处是设置DataBinder (spring提供的用于进行属性绑定的API)`,具体源码如下:
class FakeCls {
private void initDubboConfigBinder() {
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.");
}
/*
protected DubboConfigBinder createDubboConfigBinder(Environment environment) {
DefaultDubboConfigBinder defaultDubboConfigBinder = new DefaultDubboConfigBinder();
defaultDubboConfigBinder.setEnvironment(environment);
return defaultDubboConfigBinder;
}
*/
dubboConfigBinder = createDubboConfigBinder(applicationContext.getEnvironment());
}
}
// 忽略未知字段
dubboConfigBinder.setIgnoreUnknownFields(ignoreUnknownFields);
// 忽略无效字段
dubboConfigBinder.setIgnoreInvalidFields(ignoreInvalidFields);
}
}
DubboConfigBinder
是直接使用的DataBinder来绑定外部配置文件属性信息到AbstractConfig子类的属性中,源码如下:
public class DefaultDubboConfigBinder extends AbstractDubboConfigBinder {
@Override
public <C extends AbstractConfig> void bind(String prefix, C dubboConfig) {
DataBinder dataBinder = new DataBinder(dubboConfig);
// 设置忽略无效属性
dataBinder.setIgnoreInvalidFields(isIgnoreInvalidFields());
// 设置忽略未知属性
dataBinder.setIgnoreUnknownFields(isIgnoreUnknownFields());
// 从@PropertySource注解指定的配置文件中获取指定前缀的属性
Map<String, Object> properties = getSubProperties(getPropertySources(), prefix);
// 转换Map为MutablePropertyValues
MutablePropertyValues propertyValues = new MutablePropertyValues(properties);
// 调用DataBinder的API完成绑定,即设置AbstractConfig子类的属性的值
dataBinder.bind(propertyValues);
}
}
可以看到上面的代码就完成的外部属性设置到AbtractConfig子类的bean中的工作,那么是什么时候调用的呢,具体参考3.4.4:postProcessBeforeInitialization
。2021-12-30 19:29:53
处是获取并设置针对config spring bean进行定义的对象,是一个扩展的口,如下:
class FakeCls {
private void initConfigBeanCustomizers() {
// 从容器中获取类型为DubboConfigBeanCustomizer的所有spring bean
Collection<DubboConfigBeanCustomizer> configBeanCustomizers =
beansOfTypeIncludingAncestors(applicationContext, DubboConfigBeanCustomizer.class).values();
// 赋值到全局属性中,供后续使用
this.configBeanCustomizers = new ArrayList<DubboConfigBeanCustomizer>(configBeanCustomizers);
// 排序
AnnotationAwareOrderComparator.sort(this.configBeanCustomizers);
}
}
3.4.4:postProcessBeforeInitialization
通过后置bena处理器的postProcessBeforeInitialization方法,即初始化spring bean之前设置对象属性,源码如下:
class FakeCls {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals(this.beanName) && bean instanceof AbstractConfig) {
AbstractConfig dubboConfig = (AbstractConfig) bean;
// 2021-12-31 13:45:09
bind(prefix, dubboConfig);
customize(beanName, dubboConfig);
}
return bean;
}
}
2021-12-31 13:45:09
处是绑定属性,源码如下:
class FakeCls {
private void bind(String prefix, AbstractConfig dubboConfig) {
// 调用的就是DefaultDubboConfigBinder#bind方法,在"3.4.2:afterPropertiesSet"已经进行了讲解
dubboConfigBinder.bind(prefix, dubboConfig);
if (log.isInfoEnabled()) {
log.info("The properties of bean [name : " + beanName + "] have been binding by prefix of " +
"configuration properties : " + prefix);
}
}
}
到这里config bean就创建完毕并且属性也填充完毕了。dubbo配置相关的spring bean是如何创建的已经分析完了,接下来在看下第二部分重要的spring bean,即使用了@Service
注解和@Reference
注解的spring bean,dubbo定义了@DubboComponentScan
注解来定义扫描哪些目录加载使用了相关注解的类为spring bean,接着就来一起看下这部分的内容。
4:@DubboComponentScan
该注解用来扫描指定包路径下使用了@Service
和@Reference
注解的类,从而创建对应的spring bean对象,源码如下:
// 从classpath下扫描使用了@Service,@Reference注解的类自动注册为spring beans
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DubboComponentScanRegistrar.class)
public @interface DubboComponentScan {
// 设置要扫描的基础包路径
String[] value() default {};
// 设置要要扫描的包路径
String[] basePackages() default {};
// 通过设置Class来指定要扫描的基础包路径,即Class所在的包
Class<?>[] basePackageClasses() default {};
}
从@Import(DubboComponentScanRegistrar.class)
注解可以看出是通过DubboComponentScanRegistrar类来完成扫描和注册spring bean的。
4.1:DubboComponentScanRegistrar
该类处理@DubboComponentScan注解,注册@Service注解对应的ServiceAnnotationBeanPostProcessor和@Reference注解对应的ReferenceAnnotationBeanPostProcessor后置bean处理器到spring 容器中,以便对@Service和@Reference对应的spring bean进行后置处理。源码如下:
class FakeCls {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 2021-12-31 15:02:34
// 获取要扫描的包路径集合,配置@DubboComponentScan(basePackages = { "dongshi.daddy.service.multipleexternalconfig" }),这里的结果就是:
// 0 = dongshi.daddy.service.multipleexternalconfig
Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
// 2021-12-31 14:42:55
registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);
// 2021-12-31 14:43:08
registerReferenceAnnotationBeanPostProcessor(registry);
}
}
2021-12-31 14:42:55
处是设置@Service注解对应的ServiceAnnotationBeanPostProcessor,具体参考4.1.1:registerServiceAnnotationBeanPostProcessor
,2021-12-31 14:43:08
,ServiceAnnotationBeanPostProcessor具体参考4.2:ServiceAnnotationBeanPostProcessor
。处是设置@Reference注解对应的ReferenceAnnotationBeanPostProcessor,ReferenceAnnotationBeanPostProcessor具体参考4.3:ReferenceAnnotationBeanPostProcessor
。2021-12-31 15:02:34
处源码如下:
class FakeCls {
private Set<String> getPackagesToScan(AnnotationMetadata metadata) {
// 获取@DubboComponentScan配置的属性值
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
metadata.getAnnotationAttributes(DubboComponentScan.class.getName()));
// 获取basePackages,basePackageClasses,value数组,三者都是用来配置要扫描的包路径的
String[] basePackages = attributes.getStringArray("basePackages");
Class<?>[] basePackageClasses = attributes.getClassArray("basePackageClasses");
String[] value = attributes.getStringArray("value");
// 转通过value配置的包路径为set集合
Set<String> packagesToScan = new LinkedHashSet<String>(Arrays.asList(value));
// 添加通过basePackage属性配置的包路径到要扫描的包路径集合中,此时value和basePackages会做一个并集
packagesToScan.addAll(Arrays.asList(basePackages));
// 添加通过basePackageClasses配置的包路径扫到要扫描的包路径集合中,此时value,basePackages,basePakcageClasess三者做了并集
for (Class<?> basePackageClass : basePackageClasses) {
packagesToScan.add(ClassUtils.getPackageName(basePackageClass));
}
// 如果是没有要扫描的包路径,则使用当前Java config类所在包路径作为要扫描的基础包路径
// 如public class MyMultipleExternalConfigConfiguration {},所在包为package dongshi.daddy.service.multipleexternalconfig;
// 则这里的结果就是dongshi.daddy.service.multipleexternalconfig
if (packagesToScan.isEmpty()) {
return Collections.singleton(ClassUtils.getPackageName(metadata.getClassName()));
}
return packagesToScan;
}
}
4.1.1:registerServiceAnnotationBeanPostProcessor
源码如下:
class FakeCls {
private void registerServiceAnnotationBeanPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
// 构造器设计模式,创建用于构造BeanDefinition的构造器,源码如下:
/*
public static BeanDefinitionBuilder rootBeanDefinition(Class<?> beanClass, String factoryMethodName) {
BeanDefinitionBuilder builder = new BeanDefinitionBuilder();
builder.beanDefinition = new RootBeanDefinition();
builder.beanDefinition.setBeanClass(beanClass);
builder.beanDefinition.setFactoryMethodName(factoryMethodName);
return builder;
}
*/
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationBeanPostProcessor.class);
// 添加构造函数参数,这里添加的是要扫描的包路径
builder.addConstructorArgValue(packagesToScan);
// 设置角色,这里设置该bean定义为纯粹内部使用,和外部用户没有任何关系,正常可以忽略该属性
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 从构造器中获取创建的RootBeanDefinition
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
// 注册bean定义到bean定义注册器中
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
}
}
4.1.2:registerReferenceAnnotationBeanPostProcessor
源码如下:
class FakeCls {
private void registerReferenceAnnotationBeanPostProcessor(BeanDefinitionRegistry registry) {
// 获取bean名称为public static final String BEAN_NAME = "referenceAnnotationBeanPostProcessor";的bean,默认为需要的ReferenceAnnotaionBeanPostProcessor的bean,源码如下:
/*
public static void registerInfrastructureBean(BeanDefinitionRegistry beanDefinitionRegistry,
String beanName,
Class<?> beanType) {
// 不包含则重新创建并添加到bean定义注册器中
if (!beanDefinitionRegistry.containsBeanDefinition(beanName)) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanType);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
}
}
*/
BeanRegistrar.registerInfrastructureBean(registry,
ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class);
}
}
4.2:ServiceAnnotationBeanPostProcessor
4.2.1:构造方法
class FakeCls {
public ServiceAnnotationBeanPostProcessor(String... packagesToScan) {
this(Arrays.asList(packagesToScan));
}
public ServiceAnnotationBeanPostProcessor(Collection<String> packagesToScan) {
this(new LinkedHashSet<String>(packagesToScan));
}
public ServiceAnnotationBeanPostProcessor(Set<String> packagesToScan) {
this.packagesToScan = packagesToScan;
}
}
4.2.2:postProcessBeanDefinitionRegistry
因为实现了接口BeanDefinitionRegistryPostProcessor
所以会在将bean定义全部注册到BeanDefinitionRegistry之后调用postProcessBeanDefinitionRegistry方法来对bean定义注册器进行修改,
为什么要实现BeanDefinitionRegistryPostProcessor接口:因为此时spring所有能够识别的(如使用了@Component,@Bean等spring提供的注解)类都已经生成bean definition并注册到BeanDefinitionRegistry中了,但是dubbo提供的@Service注解和@Reference注解,spring的默认机制是不识别的,所以在这个节点来做,就是最合适的了。
源码如下:
class FakeCls {
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 因为可能存在占位符,所以有此步骤的占位符替换,源码如下:
/*
private Set<String> resolvePackagesToScan(Set<String> packagesToScan) {
Set<String> resolvedPackagesToScan = new LinkedHashSet<String>(packagesToScan.size());
for (String packageToScan : packagesToScan) {
if (StringUtils.hasText(packageToScan)) {
String resolvedPackageToScan = environment.resolvePlaceholders(packageToScan.trim());
resolvedPackagesToScan.add(resolvedPackageToScan);
}
}
return resolvedPackagesToScan;
}
*/
Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
// 2021-12-31 16:14:05
registerServiceBeans(resolvedPackagesToScan, registry);
} else {
if (logger.isWarnEnabled()) {
logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
}
}
}
}
2021-12-31 16:14:05
处是扫描指定的包路径集合并将有@Service注解的类生成对应的bean definition,具体参考4.2.2.1:registerServiceBeans
。
4.2.2.1:registerServiceBeans
源码如下:
class FakeCls {
private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
// 创建用于从classpath的指定包中扫描类的DubboClassPathBeanDefinitionScanner
DubboClassPathBeanDefinitionScanner scanner =
new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
// 解析获取的bean名称生成器,源码如下:
/*
private BeanNameGenerator resolveBeanNameGenerator(BeanDefinitionRegistry registry) {
BeanNameGenerator beanNameGenerator = null;
if (registry instanceof SingletonBeanRegistry) {
SingletonBeanRegistry singletonBeanRegistry = SingletonBeanRegistry.class.cast(registry);
beanNameGenerator = (BeanNameGenerator) singletonBeanRegistry.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
}
if (beanNameGenerator == null) {
// ...
beanNameGenerator = new AnnotationBeanNameGenerator();
}
return beanNameGenerator;
}
*/
BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
scanner.setBeanNameGenerator(beanNameGenerator);
// 只过滤标注了@com.alibaba.dubbo.config.annotation.Service注解的类
scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class));
// 一个包一个包的开始扫描生成bean definition
for (String packageToScan : packagesToScan) {
// 扫描注解了@com.alibaba.dubbo.config.annotation.Service注解的类的类
scanner.scan(packageToScan);
// 2021-12-31 16:52:08
Set<BeanDefinitionHolder> beanDefinitionHolders =
findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);
// 有beanDefinitionHolder,即再扫描的包路径下有标注了dubbo的@Service注解的类
if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
// 循环注册到bean定义注册器中
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
// 2022-01-01 17:04:21
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 + "]");
}
}
}
}
}
2021-12-31 16:52:08
处是封装当前包路径解析到的bean definition为BeanDefinitionHolder集合,一个bean definition对应一个BeanDefinitionHolder集合,源码如下:
class FakeCls {
private Set<BeanDefinitionHolder> findServiceBeanDefinitionHolders(
ClassPathBeanDefinitionScanner scanner, String packageToScan, BeanDefinitionRegistry registry,
BeanNameGenerator beanNameGenerator) {
// 获取扫描到的BeanDefinition集合
Set<BeanDefinition> beanDefinitions = scanner.findCandidateComponents(packageToScan);
Set<BeanDefinitionHolder> beanDefinitionHolders = new LinkedHashSet<BeanDefinitionHolder>(beanDefinitions.size());
for (BeanDefinition beanDefinition : beanDefinitions) {
// 生成bean名称
String beanName = beanNameGenerator.generateBeanName(beanDefinition, registry);
BeanDefinitionHolder beanDefinitionHolder = new BeanDefinitionHolder(beanDefinition, beanName);
beanDefinitionHolders.add(beanDefinitionHolder);
}
return beanDefinitionHolders;
}
}
2022-01-01 17:04:21
处是注册bean定义到bean定义注册器中,具体参考4.2.2.1:registerServiceBean
。
4.2.2.1:registerServiceBean
源码如下:
class FakeCls {
private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
DubboClassPathBeanDefinitionScanner scanner) {
// 从beanDefinitionHolder中获取使用了com.alibaba.dubbo.config.annotation.Service注解的服务提供者类的Class对象
Class<?> beanClass = resolveClass(beanDefinitionHolder);
// 获取Service注解对象
Service service = findAnnotation(beanClass, Service.class);
// 获取服务提供接口类型
// 2022-01-01 17:25:37
Class<?> interfaceClass = resolveServiceInterfaceClass(beanClass, service);
// 获取bean名称
String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
// 创建服务提供类对应的beandefinition对象
// 2022-01-01 20:28:22
AbstractBeanDefinition serviceBeanDefinition =
buildServiceBeanDefinition(service, interfaceClass, annotatedServiceBeanName);
// 重新生成bean名称,更具有业务含义
// ServiceBean Bean name,如ServiceBean:dubbo:dongshi.daddy.service.annotation.ProviderServiceAnnotation
String beanName = generateServiceBeanName(service, interfaceClass, annotatedServiceBeanName);
// 校验重复,不存在则中注册bean定义到bean定义注册器中
if (scanner.checkCandidate(beanName, serviceBeanDefinition)) {
// 注册
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?");
}
}
}
}
2022-01-01 17:25:37
处是获取服务提供者接口类型,源码如下:
class FakeCls {
private Class<?> resolveServiceInterfaceClass(Class<?> annotatedServiceBeanClass, Service service) {
// 首先获取在Service注解上设置的Class<?> interfaceClass() default void.class;,一般我们不设置所以是默认值void.class
Class<?> interfaceClass = service.interfaceClass();
// 如果是void.class,即获取的是默认值
if (void.class.equals(interfaceClass)) {
interfaceClass = null;
// 获取Service注解上配置的String interfaceName() default "";,默认是空串
String interfaceClassName = service.interfaceName();
// 如果是在Service注解上配置了String interfaceName() default "";
if (StringUtils.hasText(interfaceClassName)) {
// 有该类,则解析为Class对象
if (ClassUtils.isPresent(interfaceClassName, classLoader)) {
interfaceClass = resolveClassName(interfaceClassName, classLoader);
}
}
}
// 如果是执行到这里说明在Service注解上即没有设置interfaceClass也没有设置interfaceName
if (interfaceClass == null) {
// 获取所有的父接口集合,然后取第一个作为目标接口类型,此处在之前版本因为代码是Class<?>[] allInterfaces = annotatedServiceBeanClass.getInterfaces();
// 这种方式只会获取直接实现的接口,而不会递归获取父类实现的接口,因此如果不直接实现接口的话就问题了,关于该问题可以查看
// issue:https://github.com/apache/incubator-dubbo/issues/3251
Class<?>[] allInterfaces = ClassUtils.getAllInterfacesForClass(annotatedServiceBeanClass);
if (allInterfaces.length > 0) {
// 取第一个,作为结果
interfaceClass = allInterfaces[0];
}
}
// 断言获取到了class对象
Assert.notNull(interfaceClass,
"@Service interfaceClass() or interfaceName() or interface class must be present!");
// 断言获取到的class对象是接口类型
Assert.isTrue(interfaceClass.isInterface(),
"The typfe that was annotated @Service is not an interace!");
return interfaceClass;
}
}
2022-01-01 20:28:22
处是构造bean定义,具体参考4.2.2.2:buildServiceBeanDefinition
。
4.2.2.2:buildServiceBeanDefinition
源码如下:
class FakeCls {
private AbstractBeanDefinition buildServiceBeanDefinition(Service service, Class<?> interfaceClass,
String annotatedServiceBeanName) {
// ServiceBean是服务提供者service对应的配置类ServiceConfig的子类,用于进一步封装信息,这里返回的是其对应的BeanDefinition的构造器类
// 即使用的是构造器设计模式,使用构造器设计模式的原因是方便灵活设置属性信息,摆脱构造函数的束缚
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);
// 获取内部封装的ServiceBean对应的BeanDefinition
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
// 获取内部的MutablePropertyValues,方便修改属性
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
String[] ignoreAttributeNames = of("provider", "monitor", "application", "module", "registry", "protocol",
"interface", "interfaceName");
// 使用AnnotationPropertyValuesAdapter,获取dubbo @Service注解中的属性,并最终通过addPropertyValues添加到MutablePropertyValues propertyValues
// ,最终添加到ServiceBean对应的beandefinition中,如设置@Service(timeout = 5000, version = "2.3.4"),则会将timeout和version添加
propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(service, environment, ignoreAttributeNames));
// 将ServiceBean内部实际的服务提供者类的bean名称设置ref属性,个人理解是方便后续查找使用
// 也可以这样理解,是设置了ServiceBean实际引用的服务提供者类的spring bean是哪个
addPropertyReference(builder, "ref", annotatedServiceBeanName);
// 设置服务提供者类的全限定接口名称
builder.addPropertyValue("interface", interfaceClass.getName());
// 设置使用的provider的bean,如果是xml的话对应的标签就是<dubbo:provider>
String providerConfigBeanName = service.provider();
if (StringUtils.hasText(providerConfigBeanName)) {
addPropertyReference(builder, "provider", providerConfigBeanName);
}
// 获取和设置使用的monitor,对应的xml标签是<dubbo:monitor>
String monitorConfigBeanName = service.monitor();
if (StringUtils.hasText(monitorConfigBeanName)) {
addPropertyReference(builder, "monitor", monitorConfigBeanName);
}
// 获取和设置使用的application,对应的xml标签是<dubbo:application>
String applicationConfigBeanName = service.application();
if (StringUtils.hasText(applicationConfigBeanName)) {
addPropertyReference(builder, "application", applicationConfigBeanName);
}
// 获取和设置使用的module,对应的xml标签是<dubbo:module>
String moduleConfigBeanName = service.module();
if (StringUtils.hasText(moduleConfigBeanName)) {
addPropertyReference(builder, "module", moduleConfigBeanName);
}
// 获取和设置使用的registries,对应的xml标签是<dubbo:registry>
String[] registryConfigBeanNames = service.registry();
// 可能有多个,所以是List
List<RuntimeBeanReference> registryRuntimeBeanReferences = toRuntimeBeanReferences(registryConfigBeanNames);
if (!registryRuntimeBeanReferences.isEmpty()) {
builder.addPropertyValue("registries", registryRuntimeBeanReferences);
}
// 获取和设置使用的protocols,对应的xml标签是<dubbo:protocol>
String[] protocolConfigBeanNames = service.protocol();
// 可能有多个,所以是List
List<RuntimeBeanReference> protocolRuntimeBeanReferences = toRuntimeBeanReferences(protocolConfigBeanNames);
if (!protocolRuntimeBeanReferences.isEmpty()) {
builder.addPropertyValue("protocols", protocolRuntimeBeanReferences);
}
// 设置方法配置,如下可能配置:
/*
@Service(methods = {
@Method(name = "SayHelloAnnotation", timeout = 2000)
})
*/
Method[] methods = service.methods();
List<MethodConfig> methodConfigs = MethodConfig.constructMethodConfig(methods);
if(!methodConfigs.isEmpty()){
builder.addPropertyValue("methods", methodConfigs);
}
// 获取bean定义并返回
return builder.getBeanDefinition();
}
}
4.3:ReferenceAnnotationBeanPostProcessor
该后置bean处理器用于处理标注了dubbo @Reference注解的属性,实现其属性的注入,如下可能的代码:
@Component("annotatedConsumer")
public class ConsumerAnnotationService {
@Reference
private ProviderServiceAnnotation providerServiceAnnotation;
public String doSayHello(String name) {
return providerServiceAnnotation.SayHelloAnnotation(name);
}
}
所要作的事情就是为private ProviderServiceAnnotation providerServiceAnnotation
属性注入属性值。因为是属性注入,所以ReferenceAnnotationBeanPostProcessor是通过加入spring 提供的inject
相关的方法完整自定义的属性注入的,最终会执行到方法doGetInjectedBean
,我们就从这个方法开始吧!
4.3.1:doGetInjectedBean
源码如下:
class FakeCls {
@Override
protected Object doGetInjectedBean(Reference reference, Object bean, String beanName, Class<?> injectedType,
InjectionMetadata.InjectedElement injectedElement) throws Exception {
// 2022-01-02 19:17:27
String referencedBeanName = buildReferencedBeanName(reference, injectedType);
// 2022-01-02 20:42:39
ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referencedBeanName, reference, injectedType, getClassLoader());
// 添加到缓存,根据是基于属性注入还是方法注入,加入不同的缓存中,源码如下:
/*
private void cacheInjectedReferenceBean(ReferenceBean referenceBean,
InjectionMetadata.InjectedElement injectedElement) {
if (injectedElement.getMember() instanceof Field) {
// private final ConcurrentMap<InjectionMetadata.InjectedElement, ReferenceBean<?>> injectedFieldReferenceBeanCache = new ConcurrentHashMap<InjectionMetadata.InjectedElement, ReferenceBean<?>>(CACHE_SIZE);
injectedFieldReferenceBeanCache.put(injectedElement, referenceBean);
} else if (injectedElement.getMember() instanceof Method) {
// private final ConcurrentMap<InjectionMetadata.InjectedElement, ReferenceBean<?>> injectedMethodReferenceBeanCache = new ConcurrentHashMap<InjectionMetadata.InjectedElement, ReferenceBean<?>>(CACHE_SIZE);
injectedMethodReferenceBeanCache.put(injectedElement, referenceBean);
}
}
*/
cacheInjectedReferenceBean(referenceBean, injectedElement);
// 2022-01-03 10:35:17
Object proxy = buildProxy(referencedBeanName, referenceBean, injectedType);
return proxy;
}
}
2022-01-02 19:17:27
处是要生成将要引用对象的bean名称(其实就是通过netty调用远端服务提供者的代理对象)
,reference
是@Reference注解本身,injectedType
是要注入的类型,一般是接口,因为我们都是通过接口来注入对象的,具体参考4.3.1.1:buildReferencedBeanName
,2022-01-02 20:42:39
创建ReferenceBean对象,和ServiceBean对应,具体参考4.3.1.2:buildReferenceBeanIfAbsent
,2022-01-03 10:35:17
处是构建代理类,具体参考4.3.1.3:buildProxy
。
4.3.1.1:buildReferencedBeanName
源码如下:
class FakeCls {
private String buildReferencedBeanName(Reference reference, Class<?> injectedType) {
// 生成bean名称构造器对象,内容可能如下:
/*
category = "consumers"
protocol = "dubbo"
interfaceClassName = "dongshi.daddy.service.annotation.ProviderServiceAnnotation"
version = ""
group = ""
environment = null
*/
AnnotationBeanNameBuilder builder = AnnotationBeanNameBuilder.create(reference, injectedType);
// 设置环境,用于替换可能存在的占位符
builder.environment(getEnvironment());
// 替换占位符并返回结果,build方法如下:
/*
// 格式:${category}:${protocol}:${serviceInterface}:${version}:${group}
public String build() {
// 追加必须的属性信息,category:{provider|consumer}
StringBuilder beanNameBuilder = new StringBuilder(category);
// 追加协议,如dubbo,zookeeper
append(beanNameBuilder, protocol);
append(beanNameBuilder, interfaceClassName);
// 替换可选属性
append(beanNameBuilder, version);
append(beanNameBuilder, group);
String beanName = beanNameBuilder.toString();
// 替换占位符
return environment != null ? environment.resolvePlaceholders(beanName) : beanName;
}
*/
// 从build方法的源码中可以看到其实已经执行过替换占位符的操作,不知道为何这里又重复执行替换占位符操作
return getEnvironment().resolvePlaceholders(builder.build());
}
}
4.3.1.2:buildReferenceBeanIfAbsent
源码如下:
class FakeCls {
private ReferenceBean buildReferenceBeanIfAbsent(String referencedBeanName, Reference reference,
Class<?> referencedType, ClassLoader classLoader)
throws Exception {
// 先从缓存中获取,为什么要使用缓存,为了复用
ReferenceBean<?> referenceBean = referenceBeanCache.get(referencedBeanName);
// 缓存中没有
if (referenceBean == null) {
// 使用ReferenceBeanBuilder构造器类来构造ReferenceBean(又是构造器设计模式)
// 2022-01-02 20:51:45
ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder
.create(reference, classLoader, applicationContext)
.interfaceClass(referencedType);
// 构造
referenceBean = beanBuilder.build();
// 放到缓存中
referenceBeanCache.put(referencedBeanName, referenceBean);
}
// 返回
return referenceBean;
}
}
2022-01-02 20:51:45
处是使用ReferenceBeanBuilder类来构造ReferenceBean,关于ReferenceBeanBuilder类参考4.3.2:ReferenceBeanBuilder
。
4.3.1.3:buildProxy
源码如下:
class FakeCls {
private Object buildProxy(String referencedBeanName, ReferenceBean referenceBean, Class<?> injectedType) {
// 2022-01-03 19:03:53
// 生成jdk动态代理中的java.lang.reflect.InvocationHandler
InvocationHandler handler = buildInvocationHandler(referencedBeanName, referenceBean);
// 使用java.lang.reflect.Proxy#newProxyInstance方法生成jdk的动态代理类
Object proxy = Proxy.newProxyInstance(getClassLoader(), new Class[]{injectedType}, handler);
return proxy;
}
}
2022-01-03 19:03:53
处就是动态代理的核心逻辑了,提供了java.lang.reflect.InvocationHandler
实现类,执行具体的代理执行逻辑,具体参考``。
4.3.2:ReferenceBeanBuilder
4.3.3:buildInvocationHandler
源码如下:
class FakeCls {
private InvocationHandler buildInvocationHandler(String referencedBeanName, ReferenceBean referenceBean) {
// 先从缓存中获取,private final ConcurrentHashMap<String, ReferenceBeanInvocationHandler> localReferenceBeanInvocationHandlerCache = new ConcurrentHashMap<String, ReferenceBeanInvocationHandler>(CACHE_SIZE);
ReferenceBeanInvocationHandler handler = localReferenceBeanInvocationHandlerCache.get(referencedBeanName);
// 没有,new一个ReferenceBeanInvocationHandler,这是InvocationHandler的子类
// private static class ReferenceBeanInvocationHandler implements InvocationHandler {}
if (handler == null) {
// referenceBean参数:封装了服务接口的ReferenceBean对象
handler = new ReferenceBeanInvocationHandler(referenceBean);
}
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);
} else {
// Remote Reference Bean should initialize immediately
handler.init();
}
return handler;
}
}