ReferenceAnnotationBeanPostProcessor注入@ReferenceBean

 @Override
protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
                                   InjectionMetadata.InjectedElement injectedElement) throws Exception {
    /**
     * The name of bean that annotated Dubbo's {@link Service @Service} in local Spring {@link ApplicationContext}
     */
    String referencedBeanName = buildReferencedBeanName(attributes, injectedType);

    /**
     * The name of bean that is declared by {@link Reference @Reference} annotation injection
     */
    String referenceBeanName = getReferenceBeanName(attributes, injectedType);

    ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);

    boolean localServiceBean = isLocalServiceBean(referencedBeanName, referenceBean, attributes);

    registerReferenceBean(referencedBeanName, referenceBean, attributes, localServiceBean, injectedType);

    cacheInjectedReferenceBean(referenceBean, injectedElement);

    return getOrCreateProxy(referencedBeanName, referenceBean, localServiceBean, injectedType);
}
创建ReferencedBean名称(被引用)和ReferenceBean名称(引用)
/**
 * @param attributes           the attributes of {@link Reference @Reference}
 * @param serviceInterfaceType the type of Dubbo's service interface
 * @return The name of bean that annotated Dubbo's {@link Service @Service} in local Spring {@link ApplicationContext}
 */
private String buildReferencedBeanName(AnnotationAttributes attributes, Class<?> serviceInterfaceType) {
    ServiceBeanNameBuilder serviceBeanNameBuilder = create(attributes, serviceInterfaceType, getEnvironment());
    return serviceBeanNameBuilder.build();
}

在这里插入图片描述
在这里插入图片描述
首先创建一个ServiceBeanNameBuilder对象,用于创建ServiceBean的名称

private ServiceBeanNameBuilder(AnnotationAttributes attributes, Class<?> defaultInterfaceClass, Environment environment) {
	// 解析名称
    this(resolveInterfaceName(attributes, defaultInterfaceClass), environment);
    // 解析group
    this.group(getAttribute(attributes,"group"));
    // 解析版本
    this.version(getAttribute(attributes,"version"));
}

在这里插入图片描述
解析属性interfaceClass和interfaceName
在这里插入图片描述
如果没有这些参数配置,最后取接口的名称
在这里插入图片描述
然后解析group和version
最后根据解析到的各种属性创建名称

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);
}

在这里插入图片描述
可以看出这个名称是由ServiceBean:接口类名称:version:group四个部分组成的。如果version和group参数都没有配置,则只包含前两个部分。如果存在占位符,最后也会解析占位符。

上面通过@Reference注解参数和Dubbo的服务接口获取一个被引用Bean名称,下面会根据@Reference注解上面是否存在id属性再获取一个引用Bean名称。

/**
* Get the bean name of {@link ReferenceBean} if {@link Reference#id() id attribute} is present,
* or {@link #generateReferenceBeanName(AnnotationAttributes, Class) generate}.
*
* @param attributes     the {@link AnnotationAttributes attributes} of {@link Reference @Reference}
* @param interfaceClass the {@link Class class} of Service interface
* @return non-null
* @since 2.7.3
*/
private String getReferenceBeanName(AnnotationAttributes attributes, Class<?> interfaceClass) {
   // id attribute appears since 2.7.3
   String beanName = getAttribute(attributes, "id");
   if (!hasText(beanName)) {
       beanName = generateReferenceBeanName(attributes, interfaceClass);
   }
   return beanName;
}

在这里插入图片描述

构建ReferenceBean

首先考虑从缓存中获取,如果缓存中不存在则进行创建,主要是通过ReferenceBeanBuilder这个类来实现的。

/**
 * The bean name of {@link ReferenceAnnotationBeanPostProcessor}
 */
public static final String BEAN_NAME = "referenceAnnotationBeanPostProcessor";

/**
 * Cache size
 */
private static final int CACHE_SIZE = Integer.getInteger(BEAN_NAME + ".cache.size", 32);

// 本地缓存
private final ConcurrentMap<String, ReferenceBean<?>> referenceBeanCache =
        new ConcurrentHashMap<>(CACHE_SIZE);
        
private ReferenceBean buildReferenceBeanIfAbsent(String referenceBeanName, AnnotationAttributes attributes,
                                                 Class<?> referencedType)
        throws Exception {

    ReferenceBean<?> referenceBean = referenceBeanCache.get(referenceBeanName);

    if (referenceBean == null) {
        ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder
        		// 根据参数和上下文构建一个Builder独享	
                .create(attributes, applicationContext)
                // 指定被引用的类型
                .interfaceClass(referencedType);
        // 进行构造        
        referenceBean = beanBuilder.build();
        // 添加到缓存当中
        referenceBeanCache.put(referenceBeanName, referenceBean);
    } else if (!referencedType.isAssignableFrom(referenceBean.getInterfaceClass())) {
        throw new IllegalArgumentException("reference bean name " + referenceBeanName + " has been duplicated, but interfaceClass " +
                referenceBean.getInterfaceClass().getName() + " cannot be assigned to " + referencedType.getName());
    }
    return referenceBean;
}

在这里插入图片描述
首先根据注解属性和Spring容器构建一个AnnotatedInterfaceConfigBeanBuilder对象(ReferenceBeanBuilder)
在这里插入图片描述
设置接口类型
在这里插入图片描述
在这里插入图片描述
首先检查依赖,目前为空实现
执行doBuild,构造一个ReferenceBean对象

 @Override
 protected ReferenceBean doBuild() {
     return new ReferenceBean<Object>();
 }

ReferenceBean是一个比较复杂的类,下面是它的类继承结构
在这里插入图片描述
除此之外,还实现了Spring的一些接口,最重要的就是FactoryBean和InitializingBean
在这里插入图片描述
在构造的时候首先会执行父类的构造,比如ReferenceConfig
其中就包括以下的属性,通过SPI机制获取协议实现

    /**
     * The {@link Protocol} implementation with adaptive functionality,it will be different in different scenarios.
     * A particular {@link Protocol} implementation is determined by the protocol attribute in the {@link URL}.
     * For example:
     *
     * <li>when the url is registry://224.5.6.7:1234/org.apache.dubbo.registry.RegistryService?application=dubbo-sample,
     * then the protocol is <b>RegistryProtocol</b></li>
     *
     * <li>when the url is dubbo://224.5.6.7:1234/org.apache.dubbo.config.api.DemoService?application=dubbo-sample, then
     * the protocol is <b>DubboProtocol</b></li>
     * <p>
     * Actually,when the {@link ExtensionLoader} init the {@link Protocol} instants,it will automatically wraps two
     * layers, and eventually will get a <b>ProtocolFilterWrapper</b> or <b>ProtocolListenerWrapper</b>
     */
    private static final Protocol REF_PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

首先获取一个ExtensionLoader,参数为Protocol.class
在这里插入图片描述
又会触发获取一个ExtensionLoader,参数为ExtensionFactory.class
在这里插入图片描述
在这里插入图片描述
如果是ExtensionFactory类型的话,其中的objectFactory属性为null,结束继续创建
在这里插入图片描述
如果不是ExtensionFactory类型的话,则使用ExtensionFactory对应的ExtensionLoader去获取一个实现类
在这里插入图片描述
首先读取缓存,没有则创建一个,然后再缓存

 public T getAdaptiveExtension() {
      Object instance = cachedAdaptiveInstance.get();
      if (instance == null) {
          if (createAdaptiveInstanceError != null) {
              throw new IllegalStateException("Failed to create adaptive instance: " +
                      createAdaptiveInstanceError.toString(),
                      createAdaptiveInstanceError);
          }

          synchronized (cachedAdaptiveInstance) {
              instance = cachedAdaptiveInstance.get();
              if (instance == null) {
                  try {
                      instance = createAdaptiveExtension();
                      cachedAdaptiveInstance.set(instance);
                  } catch (Throwable t) {
                      createAdaptiveInstanceError = t;
                      throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
                  }
              }
          }
      }

      return (T) instance;
  }
@SuppressWarnings("unchecked")
private T createAdaptiveExtension() {
    try {
        return injectExtension((T) getAdaptiveExtensionClass().newInstance());
    } catch (Exception e) {
        throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
    }
}

private Class<?> getAdaptiveExtensionClass() {
    getExtensionClasses();
    if (cachedAdaptiveClass != null) {
        return cachedAdaptiveClass;
    }
    return cachedAdaptiveClass = createAdaptiveExtensionClass();
}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
按照相同模式

/**
 * The {@link Cluster}'s implementation with adaptive functionality, and actually it will get a {@link Cluster}'s
 * specific implementation who is wrapped with <b>MockClusterInvoker</b>
 */
private static final Cluster CLUSTER = ExtensionLoader.getExtensionLoader(Cluster.class).getAdaptiveExtension();

/**
 * A {@link ProxyFactory} implementation that will generate a reference service's proxy,the JavassistProxyFactory is
 * its default implementation
 */
private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();

在这里插入图片描述
构造完成之后需要进行配置

 protected void configureBean(C configBean) throws Exception {

     preConfigureBean(attributes, configBean);

     configureRegistryConfigs(configBean);

     configureMonitorConfig(configBean);

     configureApplicationConfig(configBean);

     configureModuleConfig(configBean);

     postConfigureBean(attributes, configBean);

 }
@Override
protected void preConfigureBean(AnnotationAttributes attributes, ReferenceBean referenceBean) {
    Assert.notNull(interfaceClass, "The interface class must set first!");
    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));
    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);
        }
    });

    // Bind annotation attributes
    dataBinder.bind(new AnnotationPropertyValuesAdapter(attributes, applicationContext.getEnvironment(), IGNORE_FIELD_NAMES));

}

配置RegistryConfig,此处为null
在这里插入图片描述
配置MonitorConfig,此处为null
在这里插入图片描述
配置ApplicationConfig,此处为null
在这里插入图片描述
配置ModuleConfig,此处为null
在这里插入图片描述
根据配置参数,后置处理

@Override
protected void postConfigureBean(AnnotationAttributes attributes, ReferenceBean bean) throws Exception {
	// 设置Spring的上下文 并将上下文对象引入到dubbo中
    bean.setApplicationContext(applicationContext);

    configureInterface(attributes, bean);

    configureConsumerConfig(attributes, bean);

    configureMethodConfig(attributes, bean);

    bean.afterPropertiesSet();

}

在这里插入图片描述
根据注解参数配置Interface信息,如果参数中没有,则读取原来的interfaceClass属性
在这里插入图片描述
配置消费者信息,此处为null

private void configureConsumerConfig(AnnotationAttributes attributes, ReferenceBean<?> referenceBean) {

    String consumerBeanName = getAttribute(attributes, "consumer");

    ConsumerConfig consumerConfig = getOptionalBean(applicationContext, consumerBeanName, ConsumerConfig.class);

    referenceBean.setConsumer(consumerConfig);

}

解析参数methods

void configureMethodConfig(AnnotationAttributes attributes, ReferenceBean<?> referenceBean) {
    Method[] methods = (Method[]) attributes.get("methods");
    List<MethodConfig> methodConfigs = MethodConfig.constructMethodConfig(methods);
    if (!methodConfigs.isEmpty()) {
        referenceBean.setMethods(methodConfigs);
    }
}

调用Bean的afterPropertiesSet方法

public void afterPropertiesSet() throws Exception {

    // Initializes Dubbo's Config Beans before @Reference bean autowiring
    prepareDubboConfigBeans();

    // lazy init by default.
    if (init == null) {
        init = false;
    }

	// 通常为false
    // eager init if necessary.
    if (shouldInit()) {
        getObject();
    }
}

准备dubbo的各种配置Bean,即进行初始化

 private void prepareDubboConfigBeans() {
     beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class);
     beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class);
     beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class);
     beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class);
     beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class);
     beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class);
     beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class);
     beansOfTypeIncludingAncestors(applicationContext, ConfigCenterBean.class);
     beansOfTypeIncludingAncestors(applicationContext, MetadataReportConfig.class);
     beansOfTypeIncludingAncestors(applicationContext, MetricsConfig.class);
     beansOfTypeIncludingAncestors(applicationContext, SslConfig.class);
 }

在这里插入图片描述
在这里插入图片描述
通过以上步骤,完成bean的创建,然后放到缓存当中
在这里插入图片描述

注册ReferenceBean

判断目标引用bean是否存在,通常为false

/**
 * Is Local Service bean or not?
 *
 * @param referencedBeanName the bean name to the referenced bean
 * @return If the target referenced bean is existed, return <code>true</code>, or <code>false</code>
 * @since 2.7.6
 */
private boolean isLocalServiceBean(String referencedBeanName, ReferenceBean referenceBean, AnnotationAttributes attributes) {
    return existsServiceBean(referencedBeanName) && !isRemoteReferenceBean(referenceBean, attributes);
}

/**
* Check the {@link ServiceBean} is exited or not
*
* @param referencedBeanName the bean name to the referenced bean
* @return if exists, return <code>true</code>, or <code>false</code>
* @revised 2.7.6
*/
private boolean existsServiceBean(String referencedBeanName) {
   return applicationContext.containsBean(referencedBeanName) &&
           applicationContext.isTypeMatch(referencedBeanName, ServiceBean.class);

}

注册一个ReferenceBean

/**
 * Register an instance of {@link ReferenceBean} as a Spring Bean
 *
 * @param referencedBeanName The name of bean that annotated Dubbo's {@link Service @Service} in the Spring {@link ApplicationContext}
 * @param referenceBean      the instance of {@link ReferenceBean} is about to register into the Spring {@link ApplicationContext}
 * @param attributes         the {@link AnnotationAttributes attributes} of {@link Reference @Reference}
 * @param localServiceBean   Is Local Service bean or not
 * @param interfaceClass     the {@link Class class} of Service interface
 * @since 2.7.3
 */
private void registerReferenceBean(String referencedBeanName, ReferenceBean referenceBean,
                                   AnnotationAttributes attributes,
                                   boolean localServiceBean, Class<?> interfaceClass) {

    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	// @Reference com.xquant.platform.test.trade.common.FacadeTradeTestService
    String beanName = getReferenceBeanName(attributes, interfaceClass);

    if (localServiceBean) {  // If @Service bean is local one
        /**
         * Get  the @Service's BeanDefinition from {@link BeanFactory}
         * Refer to {@link ServiceAnnotationBeanPostProcessor#buildServiceBeanDefinition}
         */
        AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) beanFactory.getBeanDefinition(referencedBeanName);
        RuntimeBeanReference runtimeBeanReference = (RuntimeBeanReference) beanDefinition.getPropertyValues().get("ref");
        // The name of bean annotated @Service
        String serviceBeanName = runtimeBeanReference.getBeanName();
        // register Alias rather than a new bean name, in order to reduce duplicated beans
        beanFactory.registerAlias(serviceBeanName, beanName);
    } else { // Remote @Service Bean
        if (!beanFactory.containsBean(beanName)) {
        	// 注册一个引用bean
            beanFactory.registerSingleton(beanName, referenceBean);
        }
    }
}

在这里插入图片描述

创建代理
/**
 * Get or Create a proxy of {@link ReferenceBean} for the specified the type of Dubbo service interface
 *
 * @param referencedBeanName   The name of bean that annotated Dubbo's {@link Service @Service} in the Spring {@link ApplicationContext}
 * @param referenceBean        the instance of {@link ReferenceBean}
 * @param localServiceBean     Is Local Service bean or not
 * @param serviceInterfaceType the type of Dubbo service interface
 * @return non-null
 * @since 2.7.4
 */
private Object getOrCreateProxy(String referencedBeanName, ReferenceBean referenceBean, boolean localServiceBean,
                                Class<?> serviceInterfaceType) {
    if (localServiceBean) { // If the local @Service Bean exists, build a proxy of Service
        return newProxyInstance(getClassLoader(), new Class[]{serviceInterfaceType},
                newReferencedBeanInvocationHandler(referencedBeanName));
    } else {
        exportServiceBeanIfNecessary(referencedBeanName); // If the referenced ServiceBean exits, export it immediately
        return referenceBean.get();
    }
}

进行服务bean的暴露 但是不存在 实际未进行export

private void exportServiceBeanIfNecessary(String referencedBeanName) {
	// 由于不存在 返回false
    if (existsServiceBean(referencedBeanName)) {
        ServiceBean serviceBean = getServiceBean(referencedBeanName);
        if (!serviceBean.isExported()) {
            serviceBean.export();
        }
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lang20150928

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值