Dubbo学习记录(八) -- Spring整合Dubbo中@Reference注解解析原理

Spring整合Dubbo中@Reference注解解析原理

@Reference: 可以用在属性或者方法, 意味着需要引用某个Dubbo服务, 那么Dubbo整合Spring后, 我很好奇怎么把这个过程完成的。

package org.apache.dubbo.demo.provider;
public class 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")
    @PropertySource("classpath:/spring/dubbo-provider.properties")
    static class ProviderConfiguration {

    }
}
//@EnabeDubbo注解
@EnableDubboConfig
@DubboComponentScan
public @interface EnableDubbo {

	//该属性的值也是DubboComponentScan属性basePackages的值;
    @AliasFor(annotation = DubboComponentScan.class, attribute = "basePackages")
    String[] scanBasePackages() default {};
	
    @AliasFor(annotation = DubboComponentScan.class, attribute = "basePackageClasses")
    Class<?>[] scanBasePackageClasses() default {};

    @AliasFor(annotation = EnableDubboConfig.class, attribute = "multiple")
    boolean multipleConfig() default true;
}


  • @DubboComponentScan: 用来扫描@Service 和@Reference注解修饰的类;

DubboComponentScanRegistrar

public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        System.out.println("执行DubboComponentScanRegistrar");

        // 拿到DubboComponentScan注解所定义的包路径,扫描该package下的类,识别这些类上
        Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);

        // 注册ServiceAnnotationBeanPostProcessor一个Bean
        // 实现了BeanDefinitionRegistryPostProcessor接口,所以在Spring启动时会调用postProcessBeanDefinitionRegistry方法
        // 该方法会进行扫描,扫描@Service注解了的类,然后生成BeanDefinition(会生成两个,一个普通的bean,一个ServiceBean),后续的Spring周期中会生成Bean
        // 在ServiceBean中会监听ContextRefreshedEvent事件,一旦Spring启动完后,就会进行服务导出
        registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);

        // 注册ReferenceAnnotationBeanPostProcessor
        // 实现了AnnotationInjectedBeanPostProcessor接口,继而实现了InstantiationAwareBeanPostProcessorAdapter接口
        // 所以Spring在启动时,在对属性进行注入时会调用AnnotationInjectedBeanPostProcessor接口中的postProcessPropertyValues方法
        // 在这个过程中会按照@Refrence注解的信息去生成一个RefrenceBean对象
        registerReferenceAnnotationBeanPostProcessor(registry);

    }
}

  • registerServiceAnnotationBeanPostProcessor方法用来解析@Service注解修饰的类, 最后会获得一个服务实现类, 一个ServiceBean类注入容器;
  • registerReferenceAnnotationBeanPostProcessor: 是用来解析@Reference注解的方法;

registerReferenceAnnotationBeanPostProcessor(registry)

    /**
     * Registers {@link ReferenceAnnotationBeanPostProcessor} into {@link BeanFactory}
     * 
     * @param registry {@link BeanDefinitionRegistry}
     */
    private void registerReferenceAnnotationBeanPostProcessor(BeanDefinitionRegistry registry) {

        // Register @Reference Annotation Bean Processor
        // 注册一个ReferenceAnnotationBeanPostProcessor做为bean,ReferenceAnnotationBeanPostProcessor是一个BeanPostProcessor
        BeanRegistrar.registerInfrastructureBean(registry,
                ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class);

    }

工作:

  1. 判断容器中是否包含了referenceAnnotationBeanPostProcessor名称的Bean,如果有,结束;
  2. 根据Bean的类型ReferenceAnnotationBeanPostProcessor.class,创建一个RootBeanDefinition实例;
  3. 设置Role属性;
  4. 注入容器中;
public class BeanRegistrar {

    /**
     * Register Infrastructure Bean
     *
     * @param beanDefinitionRegistry {@link BeanDefinitionRegistry}
     * @param beanType               the type of bean
     * @param beanName               the name of bean
     */
    public static void registerInfrastructureBean(BeanDefinitionRegistry beanDefinitionRegistry,
                                                  String beanName,
                                                  Class<?> beanType) {

        if (!beanDefinitionRegistry.containsBeanDefinition(beanName)) {
            RootBeanDefinition beanDefinition = new RootBeanDefinition(beanType);
            beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
        }

    }

}

ReferenceAnnotationBeanPostProcessor

  • 继承了AnnotationInjectedBeanPostProcessor类,该类又继承了MergedBeanDefinitionPostProcessor,InstantiationAwareBeanPostProcessorAdapter 类;
  • 应用启动的时候, 对于我们引入服务的类, Spring会进行对这些类进行依赖注入(类似@Autowired)
  • 依赖注入的时候会调用AnnotationInjectedBeanPostProcessor#postProcessPropertyValues()方法,这个方法里面使用了子类的处理逻辑,按照子类的处理逻辑进行依赖注入;
  • 在依赖注入前,会先执行MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法, 子类AnnotationInjectedBeanPostProcessor实现了这个接口, 目的是扫描所有被@Reference注解修饰的方法和属性的准备工作;
public class ReferenceAnnotationBeanPostProcessor extends AnnotationInjectedBeanPostProcessor implements
        ApplicationContextAware, ApplicationListener {
	//...
}
public abstract class AnnotationInjectedBeanPostProcessor extends
        InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered,
        BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean {
        //...
}
public abstract class InstantiationAwareBeanPostProcessorAdapter implements SmartInstantiationAwareBeanPostProcessor {
	//....
	@Override
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

		return pvs;
	}

}

MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法

由子类AnnotationInjectedBeanPostProcessor 实现了这个方法;

	public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor 
	void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
	}
	public abstract class AnnotationInjectedBeanPostProcessor extends
        InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered,
        BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean {
        //...
	 @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        if (beanType != null) {
            InjectionMetadata metadata = findInjectionMetadata(beanName, beanType, null);
            metadata.checkConfigMembers(beanDefinition);
        }
    }
  	} 
一、findInjectionMetadata(beanName, beanType, null)
    private InjectionMetadata findInjectionMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
        // Fall back to class name as cache key, for backwards compatibility with custom callers.
        String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
        // Quick check on the concurrent map first, with minimal locking.
        AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
        if (InjectionMetadata.needsRefresh(metadata, clazz)) {
            synchronized (this.injectionMetadataCache) {
                metadata = this.injectionMetadataCache.get(cacheKey);
                if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                    if (metadata != null) {
                        metadata.clear(pvs);
                    }
                    try {
                        metadata = buildAnnotatedMetadata(clazz);
                        this.injectionMetadataCache.put(cacheKey, metadata);
                    } catch (NoClassDefFoundError err) {
                 //...
                }
            }
        }
        return metadata;
    }
	
  • 这些元数据是通过反射获取的,由于反射本身性能不高,所以拿到一些元数据后,需要放入本地缓存injectionMetadataCache中,下次直接从缓存中获取;
  • 扫描 @Reference修饰的属性或者方法,对应类型为AnnotatedFieldElement, AnnotatedMethodElement
  • injectionMetadataCache缓存 的 key为 bean的名称,或者类的名称, 值的类型AnnotatedInjectionMetadata;
  • AnnotatedInjectionMetadata里面包装两个集合, 被@reference修饰的属性集合, 被@Reference修饰的方法集合
buildAnnotatedMetadata(clazz)

工作:

  • 获取哪些Filed上有@Reference注解
  • 获取哪些方法上有@Reference注解
  • 创建一个AnnotatedInjectionMetadata实例, 参数是属性和方法集合, 属性注入会按照这个类去进行的;返回实例;
    private AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata buildAnnotatedMetadata(final Class<?> beanClass) {

        // 扫描Field
        Collection<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> fieldElements = findFieldAnnotationMetadata(beanClass);
        // 扫描Method
        Collection<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> methodElements = findAnnotatedMethodMetadata(beanClass);
        // 返回的是Dubbo定义的AnnotatedInjectionMetadata,接下来就会使用这个类去进行属性注入
        return new AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata(beanClass, fieldElements, methodElements);

    }
  • 扫描Field
    工作:

  • 创建结果集合List;

  • 遍历beanClass的所有的Field;

  • 获取Feild上所有的注解;

  • getMergedAttributes获取@Reference注解, 如果不存在,返回空;

  • 存在@Reference注解,就会获取@reference注解的所有属性,AnnotationAttributes 存储就是注解的属性信息;

  • 存在Reference注解,就加入集合List;

   private List<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> findFieldAnnotationMetadata(final Class<?> beanClass) {

        final List<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> elements = new LinkedList<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement>();
        ReflectionUtils.doWithFields(beanClass, field -> {
            for (Class<? extends Annotation> annotationType : getAnnotationTypes()) {
                AnnotationAttributes attributes = getMergedAttributes(field, annotationType, getEnvironment(), true);

                if (attributes != null) {
				//...
                    elements.add(new AnnotatedFieldElement(field, attributes));
                }
            }
        });

        return elements;

    }
  • 扫描Method
    工作:
  1. 创建结果集合List
  2. 获取beanClass所有的Method属性
  3. 获取所有修饰Method属性的注解,遍历
  4. getMergedAttributes判断Method是否被@Reference注解修饰,有则获取注解的所有信息;
  5. 找到set方法所对应的属性;
  6. 加入结果集合List
    private List<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> findAnnotatedMethodMetadata(final Class<?> beanClass) {

        final List<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> elements = new LinkedList<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement>();

        ReflectionUtils.doWithMethods(beanClass, method -> {

            Method bridgedMethod = findBridgedMethod(method);
            for (Class<? extends Annotation> annotationType : getAnnotationTypes()) {
                AnnotationAttributes attributes = getMergedAttributes(bridgedMethod, annotationType, getEnvironment(), true);

                if (attributes != null && method.equals(ClassUtils.getMostSpecificMethod(method, beanClass))) {
					//....
                    // 找到set方法所对应的属性
                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, beanClass);
                    elements.add(new AnnotatedMethodElement(method, pd, attributes));
                }
            }
        });

        return elements;

    }

获取完之后, 退出, 返回AnnotatedInjectionMetadata到(一)步骤中的调用处,然后会将这些Field和Method信息放入缓存;

postProcessPropertyValues

InstantiationAwareBeanPostProcessorAdapter抽象类已经定义好了该方法,子类AnnotationInjectedBeanPostProcessor 重写该方法,进行@Reference的依赖注入过程;

public abstract class InstantiationAwareBeanPostProcessorAdapter implements SmartInstantiationAwareBeanPostProcessor {

	@Override
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
		return pvs;
	}
	}
}
public abstract class AnnotationInjectedBeanPostProcessor extends
        InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered,
        BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean {
	@Override
    public PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {

        // 寻找需要注入的属性(被@Reference标注的Field)
        InjectionMetadata metadata = findInjectionMetadata(beanName, bean.getClass(), pvs);
        try {
            metadata.inject(bean, beanName, pvs);
        }catch(Exception e){
        	//..异常处理
        }
        return pvs;
    }
  }  

工作:

  1. 先获取代表@Reference修饰的Field和Method信息类;在(一)步骤中,已经扫描完成,放入缓存,因此只需要先从缓存中获取;
  2. 执行属性注入;
InjectionMetadata#inject(Object target, String beanName, PropertyValues pvs)

作用: 执行属性注入
工作:

  1. 先获取被@Reference修饰的属性集合injectedElements;
  2. 遍历集合injectedElements
  3. 执行属性注入;
	public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable {
		Collection<InjectedElement> elementsToIterate =
				(this.checkedElements != null ? this.checkedElements : this.injectedElements);
		if (!elementsToIterate.isEmpty()) {
			boolean debug = logger.isDebugEnabled();
			for (InjectedElement element : elementsToIterate) {
				if (debug) {
					logger.debug("Processing injected element of bean '" + beanName + "': " + element);
				}
				element.inject(target, beanName, pvs);
			}
		}
	}
AnnotatedFieldElement#inject(target, beanName, pvs)
  • InjectedElement 是 InjectionMetadata内部类,定义了inject方法, 但是代表被@Reference修饰的属性的类是AnnotatedFieldElement
  • 该类继承了InjectedElement ,重写了inject方法, 因此调用InjectedElement 其实就是调用AnnotatedFieldElement的inject方法
    public class AnnotatedFieldElement extends InjectionMetadata.InjectedElement {}

inject工作:

  1. 获取Field的类型;
  2. 获取对象getInjectedObject
  3. 设置为可访问
  4. 反射给Field设值;
        @Override
        protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
            // 给bean对象进行属性赋值

            Class<?> injectedType = field.getType();

            // 获取对象,然后进行注入
            Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);

            ReflectionUtils.makeAccessible(field);

            // 字段赋值,injectedObject就是值
            field.set(bean, injectedObject);

        }
AnnotationInjectedBeanPostProcessor#getInjectedObject方法

获取注入属性实例;
工作:

  1. buildInjectedObjectCacheKey()生成注入对象的缓存key;
  2. 从缓存中获取 属性注入的实例;
  3. 如果存在, 直接返回;
  4. 如果不能存在, 生成属性注入的实例;
  5. 放入缓存中;
    protected Object getInjectedObject(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
                                       InjectionMetadata.InjectedElement injectedElement) throws Exception {
        // ServiceBean:org.apache.dubbo.demo.DemoService#source=private org.apache.dubbo.demo.DemoService org.apache.dubbo.demo.consumer.comp.DemoServiceComponent.demoService#attributes={parameters=[Ljava.lang.String;@42e25b0b}
        // 哪个Service应用了哪个类型的服务,通过什么方式引入的
        String cacheKey = buildInjectedObjectCacheKey(attributes, bean, beanName, injectedType, injectedElement);
        // cacheKey很鸡肋,属性名不一样的时候,cacheKey不一样,导致不能缓存, 在一个Service中@Reference两次同一个服务缓存不到

        Object injectedObject = injectedObjectsCache.get(cacheKey);

        if (injectedObject == null) {
            // 生成Bean
            injectedObject = doGetInjectedBean(attributes, bean, beanName, injectedType, injectedElement);

            // Customized inject-object if necessary
            injectedObjectsCache.putIfAbsent(cacheKey, injectedObject);
        }

        return injectedObject;

    }
ReferenceAnnotationBeanPostProcessor#doGetInjectedBean

参数:

  • attributes: 代表@Reference注解的所有配置的属性信息;
  • bean : 代表执行属性注入的类Bean实例;
  • beanName: 代表执行属性注入的类Bean实例的名称;
  • injectedType : 待注入的属性类型;

工作:

  1. 获取该属性注入的服务Bean的名称referencedBeanName ;
  2. 获取referencedBeanName属性;
  3. buildReferenceBeanIfAbsent生成一个ReferenceBean 对象;
  4. registerReferenceBean 注入到Spring容器中, 这样就可以在其他地方就可以使用@Autowired注解自动注入;
  5. cacheInjectedReferenceBean-缓存bean实例;
  6. getOrCreateProxy - 创建一个代理对象返回;也就是意味着,最后注入的属性是一个代理对象;
@Override
    protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
                                       InjectionMetadata.InjectedElement injectedElement) throws Exception {
		//该属性注入的服务Bean的名称referencedBeanName
        String referencedBeanName = buildReferencedBeanName(attributes, injectedType);

        /**
         * The name of bean that is declared by {@link Reference @Reference} annotation injection
         */
        // @Reference(methods=[Lorg.apache.dubbo.config.annotation.Method;@39b43d60) org.apache.dubbo.demo.DemoService
        // 我要生成一个RefrenceBean,对应的beanName, 根据@Reference注解来标识不同
        String referenceBeanName = getReferenceBeanName(attributes, injectedType);

        // 生成一个ReferenceBean对象
        ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);

        // 把referenceBean添加到Spring容器中去
        registerReferenceBean(referencedBeanName, referenceBean, attributes, injectedType);
		//缓存
        cacheInjectedReferenceBean(referenceBean, injectedElement);

        // 创建一个代理对象,Service中的属性被注入的就是这个代理对象
        // 内部会调用referenceBean.get();
        return getOrCreateProxy(referencedBeanName, referenceBeanName, referenceBean, injectedType);
    }
ReferenceAnnotationBeanPostProcessor#buildReferencedBeanName

创建一个ReferencedBeanName字符串;
工作:

  1. 创建一个ServiceBeanNameBuilder构建者对象, 传入@Reference注解信息, 注入的服务类型,环境信息;
  2. 生成ReferencedBeanName字符串;
  • 该名称是以 注入服务接口类名 + 版本号 + 分组名称 格式生成的;
  • 如: ServiceBean:org.apache.dubbo.demo.DemoService 表示得到该服务Bean的beanName
    private String buildReferencedBeanName(AnnotationAttributes attributes, Class<?> serviceInterfaceType) {
        ServiceBeanNameBuilder serviceBeanNameBuilder = create(attributes, serviceInterfaceType, getEnvironment());
        return serviceBeanNameBuilder.build();
    }
// ServiceBeanNameBuilder # builder()
    public String build() {
        StringBuilder beanNameBuilder = new StringBuilder("ServiceBean");
        // Required
        append(beanNameBuilder, interfaceClassName);
        // Optional
        append(beanNameBuilder, version);
        append(beanNameBuilder, group);
        // Build and remove last ":"
        String rawBeanName = beanNameBuilder.toString();
        // Resolve placeholders
        return environment.resolvePlaceholders(rawBeanName);
    }
ReferenceAnnotationBeanPostProcessor#getReferenceBeanName

获取ReferenceBeanName名称字符串;
工作:

  1. 获取注解信息中的id属性;
  2. 判断id是否为空,为空 ;generateReferenceBeanName生成一个ReferenceBeanName字符串;
  3. 返回
    private String getReferenceBeanName(AnnotationAttributes attributes, Class<?> interfaceClass) {
        // id attribute appears since 2.7.3
        String beanName = getAttribute(attributes, "id");

        // beanName为null时会进入if判断
        if (!hasText(beanName)) {
            beanName = generateReferenceBeanName(attributes, interfaceClass);
        }
        return beanName;
    }
    

generateReferenceBeanName生成一个ReferenceBeanName字符串;
工作:

  1. 获取@Reference注解信息所有属性项;
  2. 遍历属性项, 每个配置项以 “key = value ”的形式插入构造器字符串;
  3. 插入属性接口类型名称;
  4. 返回生成的ReferenceBeanName名称;
private String generateReferenceBeanName(AnnotationAttributes attributes, Class<?> interfaceClass) {
        StringBuilder beanNameBuilder = new StringBuilder("@Reference");

        if (!attributes.isEmpty()) {
            beanNameBuilder.append('(');
            for (Map.Entry<String, Object> entry : attributes.entrySet()) {
                beanNameBuilder.append(entry.getKey())
                        .append('=')
                        .append(entry.getValue())
                        .append(',');
            }
            // replace the latest "," to be ")"
            beanNameBuilder.setCharAt(beanNameBuilder.lastIndexOf(","), ')');
        }

        beanNameBuilder.append(" ").append(interfaceClass.getName());

        return beanNameBuilder.toString();
    }
referenceBeanName与referencedBeanName的区别

前者以 接口类路径名 + 版本号 + 组名 创建的;
后者以 注解所有信息 + 属性接口类型 创建的;

buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType)

目的: 创建一个ReferenceBean对象实例;
工作 :

  1. 根据生成的referenceBeanName从缓存referenceBeanCache中获取ReferenceBean实例;
  2. 存在, 直接返回
  3. 不存在,调用ReferenceBeanBuilder#build()方法就创建一个ReferenceBean对象;
  4. 不存在, 创建完Reference实例后, 放入缓存中;
  5. 返回;
    private ReferenceBean buildReferenceBeanIfAbsent(String referenceBeanName, AnnotationAttributes attributes, Class<?> referencedType)  throws Exception {
        ReferenceBean<?> referenceBean = referenceBeanCache.get(referenceBeanName);
        if (referenceBean == null) {

            // 生成了一个ReferenceBean对象,attributes是@Reference注解的参数值
            ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder
                    .create(attributes, applicationContext)
                    .interfaceClass(referencedType);
            referenceBean = beanBuilder.build();

            referenceBeanCache.put(referenceBeanName, referenceBean);
        } else if (!referencedType.isAssignableFrom(referenceBean.getInterfaceClass())) {
        //...
        }
        return referenceBean;
    }
ReferenceBeanBuilder#build()

创建一个Reference对象;
工作:

  1. 创建一个ReferenceBean对象
  2. 给ReferenceBean对象的属性赋值
    public final C build() throws Exception {

        checkDependencies();
        C configBean = doBuild();
        configureBean(configBean);
		//....

        return configBean;

    }
configureBean(C configBean)

作用: 设置ReferenceBean的属性;
工作:

  1. @Reference注解中的配置项赋值给configBean
  2. 配置注册中心;
  3. 配置监控中心;
  4. 配置Dubbo应用配置;
  5. 配置模块信息;
  6. 还是配置属性信息;
    protected void configureBean(C configBean) throws Exception {

        // 
        preConfigureBean(attributes, configBean);

        configureRegistryConfigs(configBean);

        configureMonitorConfig(configBean);

        configureApplicationConfig(configBean);

        configureModuleConfig(configBean);

        // 设置applicationContext、interfaceName、consumer、methods属性,并调用ReferenceBean对象的afterPropertiesSet方法
        postConfigureBean(attributes, configBean);

    }
    //工作流程
    //1.创建数据绑定器, 这个是Spring的内容数据绑定技术;
    //2. 去空格;
    //3. 解析并设置parameter参数;
    //4. 使用数据绑定技术, 将@Reference的基本数据设置给ReferenceBean;
   @Override
    protected void preConfigureBean(AnnotationAttributes attributes, ReferenceBean referenceBean) {
    
        DataBinder dataBinder = new DataBinder(referenceBean);
        // Register CustomEditors for special fields

        // 去掉空格
        dataBinder.registerCustomEditor(String.class, "filter", new StringTrimmerEditor(true));
        dataBinder.registerCustomEditor(String.class, "listener", new StringTrimmerEditor(true));

        // 你可以这么配@Reference(parameters = {"text=123"})
        // 也可以这么配@Reference(parameters = {"text:123"})
        // 最终都会转变为Map设置到referenceBean中的parameters
        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<String, String> parameters = CollectionUtils.toStringMap(commaDelimitedListToStringArray(content));
                setValue(parameters);
            }
        });
        
        dataBinder.bind(new AnnotationPropertyValuesAdapter(attributes, applicationContext.getEnvironment(), IGNORE_FIELD_NAMES));

    }
    //工作流程:
    //1. 设置上下文ApplicationContext;
    //2. 设置接口;
   	//3. 设置ConsumerConfig配置; 对应的是 注解里面设置 的consumer 配置信息;
   	//4. 设置Methodconfig配置
   	//4. 调用afterPropertiesSet(), 还是设置属性星系;
   	
    @Override
    protected void postConfigureBean(AnnotationAttributes attributes, ReferenceBean bean) throws Exception {

        bean.setApplicationContext(applicationContext);

        configureInterface(attributes, bean);

        configureConsumerConfig(attributes, bean);

        configureMethodConfig(attributes, bean);

        bean.afterPropertiesSet();

    }
	
	 public void afterPropertiesSet() throws Exception {
        // 这个方法还是在给ReferenceBean对象的属性赋值
        if (applicationContext != null) {
            BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ConfigCenterBean.class, false, false);
        }

        // 如果@Reference注解中没有配置consumer参数
        if (getConsumer() == null) {
            // 那么则从Spring容器中寻找ConsumerConfig类型的Bean, 比如通过@Bean定义了一个ConsumerConfig的Bean
            Map<String, ConsumerConfig> consumerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class, false, false);

            if (consumerConfigMap != null && consumerConfigMap.size() > 0) {
                ConsumerConfig consumerConfig = null;

                // 可能存在多个ConsumerConfig类型的Bean,遍历这些Bean,取第一个没有配置default或者default为true的Bean作为consumer的值
                for (ConsumerConfig config : consumerConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault()) {
                        if (consumerConfig != null) {
                            throw new IllegalStateException("Duplicate consumer configs: " + consumerConfig + " and " + config);
                        }
                        consumerConfig = config;
                    }
                }
                if (consumerConfig != null) {
                    setConsumer(consumerConfig);
                }
            }
        }


        if (getApplication() == null
                && (getConsumer() == null || getConsumer().getApplication() == null)) {
            Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);
            if (applicationConfigMap != null && applicationConfigMap.size() > 0) {
                ApplicationConfig applicationConfig = null;
                for (ApplicationConfig config : applicationConfigMap.values()) {
                    if (applicationConfig != null) {
                        throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config);
                    }
                    applicationConfig = config;
                }
                if (applicationConfig != null) {
                    setApplication(applicationConfig);
                }
            }
        }
        if (getModule() == null
                && (getConsumer() == null || getConsumer().getModule() == null)) {
            Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);
            if (moduleConfigMap != null && moduleConfigMap.size() > 0) {
                ModuleConfig moduleConfig = null;
                for (ModuleConfig config : moduleConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault()) {
                        if (moduleConfig != null) {
                            throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config);
                        }
                        moduleConfig = config;
                    }
                }
                if (moduleConfig != null) {
                    setModule(moduleConfig);
                }
            }
        }

        // 如果@Reference注解上没有配置registryIds
        // 那么则看application或consumer上有没有配置registryIds
        if (StringUtils.isEmpty(getRegistryIds())) {
            if (getApplication() != null && StringUtils.isNotEmpty(getApplication().getRegistryIds())) {
                setRegistryIds(getApplication().getRegistryIds());
            }
            if (getConsumer() != null && StringUtils.isNotEmpty(getConsumer().getRegistryIds())) {
                setRegistryIds(getConsumer().getRegistryIds());
            }

        }

        if (CollectionUtils.isEmpty(getRegistries())
                && (getConsumer() == null || CollectionUtils.isEmpty(getConsumer().getRegistries()))
                && (getApplication() == null || CollectionUtils.isEmpty(getApplication().getRegistries()))) {
            Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
            if (registryConfigMap != null && registryConfigMap.size() > 0) {
                List<RegistryConfig> registryConfigs = new ArrayList<>();
                if (StringUtils.isNotEmpty(registryIds)) {
                    Arrays.stream(COMMA_SPLIT_PATTERN.split(registryIds)).forEach(id -> {
                        if (registryConfigMap.containsKey(id)) {
                            registryConfigs.add(registryConfigMap.get(id));
                        }
                    });
                }

                if (registryConfigs.isEmpty()) {
                    for (RegistryConfig config : registryConfigMap.values()) {
                        if (StringUtils.isEmpty(registryIds)) {
                            registryConfigs.add(config);
                        }
                    }
                }
                if (!registryConfigs.isEmpty()) {
                    super.setRegistries(registryConfigs);
                }
            }
        }

        if (getMetadataReportConfig() == null) {
            Map<String, MetadataReportConfig> metadataReportConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MetadataReportConfig.class, false, false);
            if (metadataReportConfigMap != null && metadataReportConfigMap.size() == 1) {
                // first elements
                super.setMetadataReportConfig(metadataReportConfigMap.values().iterator().next());
            } else if (metadataReportConfigMap != null && metadataReportConfigMap.size() > 1) {
                throw new IllegalStateException("Multiple MetadataReport configs: " + metadataReportConfigMap);
            }
        }

        // 如果@Reference注解中没有配置configCenter属性
        // 那么则从Spring容器中找ConfigCenterConfig类型的bean
        if (getConfigCenter() == null) {
            Map<String, ConfigCenterConfig> configenterMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ConfigCenterConfig.class, false, false);

            // 只能配一个ConfigCenterConfig
            if (configenterMap != null && configenterMap.size() == 1) {
                // 设置进去
                super.setConfigCenter(configenterMap.values().iterator().next());
            } else if (configenterMap != null && configenterMap.size() > 1) {
                throw new IllegalStateException("Multiple ConfigCenter found:" + configenterMap);
            }
        }

        if (getMonitor() == null
                && (getConsumer() == null || getConsumer().getMonitor() == null)
                && (getApplication() == null || getApplication().getMonitor() == null)) {
            Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);
            if (monitorConfigMap != null && monitorConfigMap.size() > 0) {
                MonitorConfig monitorConfig = null;
                for (MonitorConfig config : monitorConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault()) {
                        if (monitorConfig != null) {
                            throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config);
                        }
                        monitorConfig = config;
                    }
                }
                if (monitorConfig != null) {
                    setMonitor(monitorConfig);
                }
            }
        }

        if (getMetrics() == null) {
            Map<String, MetricsConfig> metricsConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MetricsConfig.class, false, false);
            if (metricsConfigMap != null && metricsConfigMap.size() > 0) {
                MetricsConfig metricsConfig = null;
                for (MetricsConfig config : metricsConfigMap.values()) {
                    if (metricsConfig != null) {
                        throw new IllegalStateException("Duplicate metrics configs: " + metricsConfig + " and " + config);
                    }
                    metricsConfig = config;
                }
                if (metricsConfig != null) {
                    setMetrics(metricsConfig);
                }
            }
        }

        if (shouldInit()) {
            getObject();
        }
    }
registerReferenceBean(referencedBeanName, referenceBean, attributes, injectedType)

目的:将ReferenceBean注入容器, 这个步骤中,会将服务实现类注入容器,这样一个地方使用@Reference注解后,其他地方就可以通过@Autowired自动注入了。
工作:

  1. 获取Bean工厂;
  2. 获取referenceBeanName字符串, 将@Reference注解内容以键值对拼接 + 服务接口名; (应该是重复操作了)
  3. 判断容器是否已经存在这个Bean了。如果存在,则是本地服务(@Service注解修饰的服务在@Reference注解之前解析完成了)
  • 存在的话,则根据referenceBeanName去BeanFactory中获取 代表@Service注解的ServiceBean的BeanDefinition;

  • 获取ServiceBean的ref属性;

  • 获取ServiceBean的名称;

  • 注册别名,如果别名和ServiceBean的别名一样,就不需要注册别名, 不一样就以ServiceBean的Bean名称为键, referenceBeanName为值,放入别名缓冲中;

  • 不存在的话,就往容器中注入生成的referenceBean;

    private void registerReferenceBean(String referencedBeanName, ReferenceBean referenceBean,
                                       AnnotationAttributes attributes,
                                       Class<?> interfaceClass) {

        ConfigurableListableBeanFactory beanFactory = getBeanFactory();

        String beanName = getReferenceBeanName(attributes, interfaceClass);

        if (existsServiceBean(referencedBeanName)) { // If @Service bean is local one
            AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) beanFactory.getBeanDefinition(referencedBeanName);
            RuntimeBeanReference runtimeBeanReference = (RuntimeBeanReference) beanDefinition.getPropertyValues().get("ref"); // ServiceBean --- ref
            String serviceBeanName = runtimeBeanReference.getBeanName();
            beanFactory.registerAlias(serviceBeanName, beanName);
        } else { // Remote @Service Bean
            if (!beanFactory.containsBean(beanName)) {
                beanFactory.registerSingleton(beanName, referenceBean);
            }
        }
    }
cacheInjectedReferenceBean(referenceBean, injectedElement)

目的: 将生成的referenceBean实例,放入缓存;

  • 如果是属性注入, 则放入injectedFieldReferenceBeanCache中;
  • 如果是方法注入, 则放入injectedMethodReferenceBeanCache中;
    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);
        }
    }
getOrCreateProxy(referencedBeanName, referenceBeanName, referenceBean, injectedType)

目的: 创建一个代理对象返回;
为什么是代理对象,而不是上面容器中的服务实现类;
个人看法:
不同服务,分布在不同的机器上,如果是本地服务还好, 如果是远程服务, 在调用服务还需要额外操作,
例如负载均衡, 注册中心等功能;因此,不能直接返回服务实现类,而是返回代理对象, 公共的操作让代理对象去执行;

工作:

  1. 判断ServiceBean是否存在,存在则是本地服务, 不存在则是远程服务;
  2. 本地服务:会生成一个代理对象,代理对象的InvocationHandler会放入缓存中, 返回代理对象;
  3. 远程服务:调用get()获取一个代理对象返回;
    private Object getOrCreateProxy(String referencedBeanName, String referenceBeanName, ReferenceBean referenceBean, Class<?> serviceInterfaceType) {
        if (existsServiceBean(referencedBeanName)) { // If the local @Service Bean exists, build a proxy of ReferenceBean
            return newProxyInstance(getClassLoader(), new Class[]{serviceInterfaceType},
                    wrapInvocationHandler(referenceBeanName, referenceBean));
        } else {                                    // ReferenceBean should be initialized and get immediately
            // 重点
            return referenceBean.get();
        }
    }
private InvocationHandler wrapInvocationHandler(String referenceBeanName, ReferenceBean referenceBean) {
        return localReferenceBeanInvocationHandlerCache.computeIfAbsent(referenceBeanName, name ->
                new ReferenceBeanInvocationHandler(referenceBean));
    }

总结

@Reference注解服务引入的过程:

有了这些逻辑,@Reference注解服务引入的过程是这样的:

  1. 得到当前所引入服务对应的ServiceBean的beanName(源码中叫referencedBeanName)
  2. 根据@Reference注解的所有信息+属性接口类型得到一个referenceBeanName
  3. 根据referenceBeanName从referenceBeanCache获取对应的ReferenceBean,如果没有则创建一个ReferenceBean
  4. 根据referencedBeanName(ServiceBean的beanName)判断Spring容器中是否存在该bean,如果存在则给ref属性所对应的bean取一个别名,别名为referenceBeanName。
    a. 如果Spring容器中不存在referencedBeanName对应的bean,则判断容器中是否存在referenceBeanName所对应的Bean,如果不存在则将创建出来的ReferenceBean注册到Spring容器中(此处这么做就支持了可以通过@Autowired注解也可以使用服务了,ReferenceBean是一个FactoryBean)
  5. 如果referencedBeanName存在对应的Bean,则额外生成一个代理对象,代理对象的InvocationHandler会缓存在localReferenceBeanInvocationHandlerCache中,这样如果引入的是同一个服务,并且这个服务在本地,
  6. 如果referencedBeanName不存在对应的Bean,则直接调用ReferenceBean的get()方法得到一个代理对象
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Spring Cloud Alibaba和Dubbo3是两个不同的框架,目前还没有官方提供的整合方案。不过,我们可以使用Dubbo注解方式来整合它们。 首先,我们需要依赖相关的库,在pom.xml文件添加以下依赖: ``` <dependencies> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-springboot-starter</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-registry-nacos</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-alibaba-dubbo</artifactId> <version>2.2.3.RELEASE</version> </dependency> </dependencies> ``` 然后,在Spring Boot的启动类上添加以下注解,启用Dubbo注解扫描和自动配置: ``` @SpringBootApplication @EnableDubbo(scanBasePackages = "com.example.service") //指定需要扫描的包路径 public class Dubbo3DemoApplication { public static void main(String[] args) { SpringApplication.run(Bootstrap.class, args); } } ``` 接下来,我们需要在服务实现类上添加Dubbo相关的注解,例如: ``` @Service(version = "1.0.0") public class UserServiceImpl implements UserService { // 实现方法... } ``` 最后,在application.properties或application.yml配置Dubbo的相关属性,例如: ``` spring.application.name=dubbo3-demo spring.cloud.alibaba.dubbo.registry.address=nacos://localhost:8848 spring.cloud.alibaba.dubbo.registry.group=DEFAULT_GROUP spring.cloud.alibaba.dubbo.registry.namespace=your-namespace ``` 完成以上步骤后,我们可以使用Dubbo注解,如@Reference注解来引用其他服务。 需要注意的是,对于Spring Cloud Alibaba和Dubbo3的整合,目前还处于较早的阶段,可能存在一些不稳定性和兼容性问题。建议在实际开发进行充分的评估和测试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值