Dubbo2.7详解( 五 )

【5】扫描@Reference注解 , 并且进行处理
1)ReferenceAnnotationBeanPostProcessor类会被调用是基于继承关系
//class ReferenceAnnotationBeanPostProcessor extends AnnotationInjectedBeanPostProcessor//abstract class AnnotationInjectedBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter//InstantiationAwareBeanPostProcessorAdapter类便是属性注入时候会调用的//调用AnnotationInjectedBeanPostProcessor抽象类的postProcessPropertyValues方法@Overridepublic PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {// 寻找需要注入的属性(被@Reference标注的Field)InjectionMetadata metadata = https://www.huyubaike.com/biancheng/findInjectionMetadata(beanName, bean.getClass(), pvs);try {metadata.inject(bean, beanName, pvs);} catch (BeanCreationException ex) {throw ex;} catch (Throwable ex) {throw new BeanCreationException(beanName,"Injection of @" + getAnnotationType().getSimpleName()+ " dependencies is failed", ex);}return pvs;}//最终走回到ReferenceAnnotationBeanPostProcessor类的doGetInjectedBean方法2)ReferenceAnnotationBeanPostProcessor中的方法
public class ReferenceAnnotationBeanPostProcessor extends AnnotationInjectedBeanPostProcessor implements ApplicationContextAware, ApplicationListener {...// 该方法得到的对象会赋值给@ReferenceBean注解的属性@Overrideprotected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,InjectionMetadata.InjectedElement injectedElement) throws Exception {// 得到引入服务的beanName// attributes里存的是@Reference注解中的所配置的属性与值// injectedType表示引入的是哪个服务接口// referencedBeanName的值为ServiceBean:org.apache.dubbo.demo.DemoService表示得到该服务Bean的beanName// referencedBeanName表示 我现在要引用的这个服务 , 它导出时对应的ServiceBean的beanName是什么,可以用来判断现在我引用的这个服务是不是我自己导出的String referencedBeanName = buildReferencedBeanName(attributes, injectedType);// @Reference(methods=[Lorg.apache.dubbo.config.annotation.Method;@39b43d60) org.apache.dubbo.demo.DemoService// 我要生成一个RefrenceBean,对应的beanName,根据@Reference注解来标识不同String referenceBeanName = getReferenceBeanName(attributes, injectedType);// 生成一个ReferenceBean对象,方法1ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);// 把referenceBean添加到Spring容器中去,方法2registerReferenceBean(referencedBeanName, referenceBean, attributes, injectedType);cacheInjectedReferenceBean(referenceBean, injectedElement);// 创建一个代理对象 , Service中的属性被注入的就是这个代理对象// 内部会调用referenceBean.get(); ,核心方法1return getOrCreateProxy(referencedBeanName, referenceBeanName, referenceBean, injectedType);}//方法1private 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())) {throw new IllegalArgumentException(...);}return referenceBean;}//方法2private void registerReferenceBean(String referencedBeanName, ReferenceBean referenceBean, AnnotationAttributes attributes, Class<?> interfaceClass) {ConfigurableListableBeanFactory beanFactory = getBeanFactory();// @Reference(parameters=[Ljava.lang.String;@72ef8d15) org.apache.dubbo.demo.DemoService// ReferenceBean的beanName,注意这个beanName,它是直接取的@Reference的全信息// 所以,就算引用的是同一个服务,如果@Reference注解上的信息不同,那么就会生成不同的ReferenceBeanString beanName = getReferenceBeanName(attributes, interfaceClass);// 要引入的服务就是本地提供的一个服务if (existsServiceBean(referencedBeanName)) { // If @Service bean is local one/*** Getthe @Service's BeanDefinition from {@link BeanFactory}* Refer to {@link ServiceAnnotationBeanPostProcessor#buildServiceBeanDefinition}*/AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) beanFactory.getBeanDefinition(referencedBeanName);RuntimeBeanReference runtimeBeanReference = (RuntimeBeanReference) beanDefinition.getPropertyValues().get("ref"); // ServiceBean --- ref// The name of bean annotated @ServiceString serviceBeanName = runtimeBeanReference.getBeanName();// register Alias rather than a new bean name, in order to reduce duplicated beans// 如果是本地提供的一个服务 , 那么就@Reference(parameters=[Ljava.lang.String;@72ef8d15) org.apache.dubbo.demo.DemoService// 的别名是demoService,不需要是ServiceBean的名字beanFactory.registerAlias(serviceBeanName, beanName);} else { // Remote @Service Beanif (!beanFactory.containsBean(beanName)) {beanFactory.registerSingleton(beanName, referenceBean);}}}//核心方法1//这里面其实有点绕,因为@Reference其实也相当于做了@Autowired的工作//能在本地找到,如果不代理的话其实相当于@Autowired注入属性(不会走Dubbo的逻辑),所以包装成代理,让它也走Dubbo的逻辑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//进行代理,让它走Dubbo的逻辑return newProxyInstance(getClassLoader(), new Class[]{serviceInterfaceType}, wrapInvocationHandler(referenceBeanName, referenceBean));} else {// ReferenceBean should be initialized and get immediately// 重点,服务引入的地方return referenceBean.get();}}...}

推荐阅读