dubbo @Reference 注解注入原理

问题:

被@Reference 注解的 bean,是在什么时机注入的?
被@Reference 注解的 bean,通常是一个接口,怎么可以被实例化呢?
答案是:

@Reference 的注入时机和 @Autowired 注解是类似的,但不完全一样。负责修饰 bean 属性的 BeanFactoryPostProcessor不同。
@Reference修饰的域是通过动态代理实现的。也就是生成了一个动态的接口实现类。

在github上https://github.com/alibaba/dubbo-spring-boot-starter下载了dubbo-spring-boot-starter

在spring.factories文件中找到DubboConsumerAutoConfiguration类

@Configuration
@ConditionalOnClass(Service.class)
@ConditionalOnBean(annotation = EnableDubboConfiguration.class)
@AutoConfigureAfter(DubboAutoConfiguration.class)
@EnableConfigurationProperties(DubboProperties.class)
public class DubboConsumerAutoConfiguration extends DubboCommonAutoConfiguration {
  private static final Map<ClassIdBean, Object> DUBBO_REFERENCES_MAP =
      new ConcurrentHashMap<ClassIdBean, Object>();

  @Autowired
  private ApplicationContext applicationContext;
  @Autowired
  private DubboProperties properties;

  public static Object getDubboReference(ClassIdBean classIdBean) {
    return DUBBO_REFERENCES_MAP.get(classIdBean);
  }

  @Bean
  public BeanPostProcessor beanPostProcessor() {
    return new BeanPostProcessor() {

      @Override
      public Object postProcessBeforeInitialization(Object bean, String beanName)
          throws BeansException {
        Class<?> objClz;
        if (AopUtils.isAopProxy(bean)) {
          objClz = AopUtils.getTargetClass(bean);
        } else {
          objClz = bean.getClass();
        }

        try {
          for (Field field : objClz.getDeclaredFields()) {
          //判断该字段是否有 Reference 注解
            Reference reference = field.getAnnotation(Reference.class);
            if (reference != null) {
              DubboConsumerAutoConfiguration.this
                  .initIdConfigMap(DubboConsumerAutoConfiguration.this.properties);
              ReferenceBean<?> referenceBean =
                  DubboConsumerAutoConfiguration.this.getConsumerBean(beanName, field, reference);
              Class<?> interfaceClass = referenceBean.getInterfaceClass();
              String group = referenceBean.getGroup();
              String version = referenceBean.getVersion();
              ClassIdBean classIdBean = new ClassIdBean(interfaceClass, group, version);
              Object dubboReference =
                  DubboConsumerAutoConfiguration.DUBBO_REFERENCES_MAP.get(classIdBean);
              if (dubboReference == null) {
                synchronized (this) {
                  // double check
                  dubboReference =
                      DubboConsumerAutoConfiguration.DUBBO_REFERENCES_MAP.get(classIdBean);
                  if (dubboReference == null) {
                    referenceBean.afterPropertiesSet();
                    // dubboReference should not be null, otherwise it will cause
                    // NullPointerException
					//获取 dubbo reference,也就是代理类
                    dubboReference = referenceBean.getObject();
                    DubboConsumerAutoConfiguration.DUBBO_REFERENCES_MAP.put(classIdBean,
                        dubboReference);
                  }
                }
              }
              field.setAccessible(true);
              field.set(bean, dubboReference);
            }
          }
        } catch (Exception e) {
          throw new BeanCreationException(beanName, e);
        }
        return bean;
      }
...
}

ReferenceBean 的getObject()方法就是进入到ReferenceBean 类中,和xml配置就是相同的了

注意点:

  new BeanPostProcessor(){重写postProcessBeforeInitialization方法},在spring 容器中注册bean后,会自动应用在容器中。在所有Bean实例化之后进行判断其属性字段上是否有 @Reference 注解。

原创文章 317 获赞 416 访问量 112万+

猜你喜欢

转载自blog.csdn.net/u014082714/article/details/101033369