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可以参考:
            // https://blog.csdn.net/wang0907/article/details/114798943
            // https://blog.csdn.net/wang0907/article/details/115440135
            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:registerServiceAnnotationBeanPostProcessor2021-12-31 14:43:08,ServiceAnnotationBeanPostProcessor具体参考4.2:ServiceAnnotationBeanPostProcessor。处是设置@Reference注解对应的ReferenceAnnotationBeanPostProcessor,ReferenceAnnotationBeanPostProcessor具体参考4.3:ReferenceAnnotationBeanPostProcessor2021-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:buildReferencedBeanName2022-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;
    }
}
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐