美文网首页
4.Dubbo源码分析----Reference标签的处理

4.Dubbo源码分析----Reference标签的处理

作者: szhlcy | 来源:发表于2019-04-09 21:39 被阅读0次

     前面对于Service标签的处理已经说明了Dubbo源码分析----Dubbo的Service注解分析
    ,现在对Reference标签的处理进行解释。
     对于Reference标签的解析还是按照前面的分析找到ReferenceAnnotationBeanPostProcessor类这个类是dubbo中AnnotationInjectedBeanPostProcessor的子类,而AnnotationInjectedBeanPostProcessor类又继承了spring的AnnotationInjectedBeanPostProcessor类同时实现了MergedBeanDefinitionPostProcessor类。

    类图
     其中AnnotationInjectedBeanPostProcessor重载了postProcessPropertyValues跟postProcessMergedBeanDefinition方法,对于这两个方法先进行说明。
    • postProcessPropertyValues:这个方法是InstantiationAwareBeanPostProcessor接口中定义的,作用是对实例化之后属性设置之前Bean 的属性值进行修改。调用这个方法的前提是postProcessAfterInstantiation方法返回true,其中postProcessAfterInstantiation方法在InstantiationAwareBeanPostProcessorAdapter默认返回是true。
    • postProcessMergedBeanDefinition:这个方法是在MergedBeanDefinitionPostProcessor类中定义的,作用是在Bean合并之后回调用,也就是Bean属性填充完毕之后。

      所以按顺序,现在先进入到postProcessPropertyValues方法中。
        @Override
        public PropertyValues postProcessPropertyValues(
                PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
            //获取注入用的元数据
            InjectionMetadata metadata = 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().getName()
                        + " dependencies is failed", ex);
            }
            return pvs;
        }
    

    postProcessPropertyValues方法主要是对Bean中的属性的获取,其中InjectionMetadata对象是spring中用于管理注入元数据的内部类。现在进入findInjectionMetadata方法

        private InjectionMetadata findInjectionMetadata(String beanName, Class<?> clazz, PropertyValues pvs) {
            // Fall back to class name as cache key, for backwards compatibility with custom callers.
            //生成缓存的cacheKey
            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);
            //如果元数据是空的,或者元数据缓存中保存的Class对象不是传入的Class对象
            if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                synchronized (this.injectionMetadataCache) {
                    metadata = this.injectionMetadataCache.get(cacheKey);
                    //双重检查锁
                    if (InjectionMetadata.needsRefresh(metadata, clazz)) {
                        //如果元数据不是null就对其中的属性进行清空
                        if (metadata != null) {
                            metadata.clear(pvs);
                        }
                        try {
                            //创建元数据
                            metadata = buildAnnotatedMetadata(clazz);
                            //放到缓存中进行保存
                            this.injectionMetadataCache.put(cacheKey, metadata);
                        } catch (NoClassDefFoundError err) {
                            throw new IllegalStateException("Failed to introspect object class [" + clazz.getName() +
                                    "] for annotation metadata: could not find class that it depends on", err);
                        }
                    }
                }
            }
            return metadata;
        }
    

    上面的逻辑也比较简单,就是先检查缓存和比较Class对象判断是不是同一个,如果缓存为空或者缓存的Class对象不是传入的Class对象,就需要先进行缓存的清楚然后创建InjectionMetadata进行保存。现在对元数据的创建进行解析

        private AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata buildAnnotatedMetadata(final Class<?> beanClass) {
            //获取AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement
            Collection<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> fieldElements = findFieldAnnotationMetadata(beanClass);
            //获取AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement
            Collection<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> methodElements = findAnnotatedMethodMetadata(beanClass);
            //上面的两个集合中的对象都是spring中InjectionMetadata类的内部类InjectedElement的继承类用来保存单个元素
            return new AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata(beanClass, fieldElements, methodElements);
    
        }
        
    //-------------
    
            private List<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> findFieldAnnotationMetadata(final Class<?> beanClass) {
    
            final List<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> elements = new LinkedList<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement>();
            // 通过反射的工具类,获取当前beanClass中的所有Field,然后通过实现ReflectionUtils类的内部类FieldCallback的实现,来对字段进行处理
            ReflectionUtils.doWithFields(beanClass, new ReflectionUtils.FieldCallback() {
                @Override
                public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                    //获取field里面的Reference标签
                    A annotation = getAnnotation(field, getAnnotationType());
                    //检查标签是不是null
                    if (annotation != null) {
                        //field不是static类型的
                        if (Modifier.isStatic(field.getModifiers())) {
                            if (logger.isWarnEnabled()) {
                                logger.warn("@" + getAnnotationType().getName() + " is not supported on static fields: " + field);
                            }
                            return;
                        }
                        //创建AnnotatedFieldElement并放到集合中
                        elements.add(new AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement(field, annotation));
                    }
    
                }
            });
            return elements;
        }
    //--------------------
        private List<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> findAnnotatedMethodMetadata(final Class<?> beanClass) {
    
            final List<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> elements = new LinkedList<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement>();
            //获取到beanClass中所有的Method,然后调用实现的ReflectionUtils.MethodCallback类的doWith方法
            ReflectionUtils.doWithMethods(beanClass, new ReflectionUtils.MethodCallback() {
                @Override
                public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
                    //寻找method的桥接方法,关于桥接方法这是在Java1.5引入泛型之后,编译器为了向前兼容,生成这个的
                    Method bridgedMethod = findBridgedMethod(method);
                    //检查是不是可见的桥接方法
                    if (!isVisibilityBridgeMethodPair(method, bridgedMethod)) {
                        return;
                    }
                    //找到方法上的Reference标签
                    A annotation = findAnnotation(bridgedMethod, getAnnotationType());
                    //如果标签不是bull并且找到beanClass中的具体的方法
                    if (annotation != null && method.equals(ClassUtils.getMostSpecificMethod(method, beanClass))) {
                        //方法不能是静态的
                        if (Modifier.isStatic(method.getModifiers())) {
                            if (logger.isWarnEnabled()) {
                                logger.warn("@" + getAnnotationType().getSimpleName() + " annotation is not supported on static methods: " + method);
                            }
                            return;
                        }
                        //需要有参数
                        if (method.getParameterTypes().length == 0) {
                            if (logger.isWarnEnabled()) {
                                logger.warn("@" + getAnnotationType().getSimpleName() + " annotation should only be used on methods with parameters: " +
                                        method);
                            }
                        }
                        //获取beanClass中指定方法的属性
                        PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, beanClass);
                        elements.add(new AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement(method, pd, annotation));
                    }
                }
            });
            return elements;
        }
    

     上面分析了从传入的Bean中获取对应的元数据后保存到InjectionMetadata对象中,现在就是进行注入了。inject方法也是一个模板方法,首先调用的InjectionMetadata的inject然后调用AnnotationInjectedBeanPostProcessor类中的内部类实现的inject方法。

    //InjectionMetadata中的inject
        public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            Collection<InjectedElement> checkedElements = this.checkedElements;
            //如果checkedElements为空就使用传入的injectedElements,这里传入的是fieldElements, methodElements两个的组合
            Collection<InjectedElement> elementsToIterate =
                    (checkedElements != null ? checkedElements : this.injectedElements);
            if (!elementsToIterate.isEmpty()) {
                //迭代然后调用实现的inject方法
                for (InjectedElement element : elementsToIterate) {
                    if (logger.isTraceEnabled()) {
                        logger.trace("Processing injected element of bean '" + beanName + "': " + element);
                    }
                    element.inject(target, beanName, pvs);
                }
            }
        }
    //-----------------------内部类AnnotatedFieldElement跟AnnotatedMethodElement中的方法
        protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
            //获取类型
            Class<?> injectedType = field.getType();
            //获取注入之后的对象
            Object injectedObject = getInjectedObject(annotation, bean, beanName, injectedType, this);
            //如果是私有字段先设置makeAccessible属性
            ReflectionUtils.makeAccessible(field);
            //给Bean对象设置诸如之后的对象
            field.set(bean, injectedObject);
        }
    //------getInjectedObject方法
        protected Object getInjectedObject(A annotation, Object bean, String beanName, Class<?> injectedType,
                                           InjectionMetadata.InjectedElement injectedElement) throws Exception {
            //构建缓存对的key
            String cacheKey = buildInjectedObjectCacheKey(annotation, bean, beanName, injectedType, injectedElement);
            //先查询缓存
            Object injectedObject = injectedObjectsCache.get(cacheKey);
            //缓存为null
            if (injectedObject == null) {
                //创建注入之后的对象
                injectedObject = doGetInjectedBean(annotation, bean, beanName, injectedType, injectedElement);
                // Customized inject-object if necessary
                injectedObjectsCache.putIfAbsent(cacheKey, injectedObject);
            }
            return injectedObject;
        }
    //------doGetInjectedBean方法
        protected Object doGetInjectedBean(Reference reference, Object bean, String beanName, Class<?> injectedType,
                                           InjectionMetadata.InjectedElement injectedElement) throws Exception {
            //创建应用Bean 的name,根据接口的名称,类型,group等拼接进行闯进
            String referencedBeanName = buildReferencedBeanName(reference, injectedType);
            //如果不存在则创建ReferenceBean对象
            ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referencedBeanName, reference, injectedType, getClassLoader());
            //保存到缓存中
            cacheInjectedReferenceBean(referenceBean, injectedElement);
            //创建reference的代理类
            Object proxy = buildProxy(referencedBeanName, referenceBean, injectedType);
            //返回
            return proxy;
        }
    

    上面就就是对@Reference标签的处理过程,根据获取到的元数据,最后创建一个贴有@Reference标签的接口的代理类。

    相关文章

      网友评论

          本文标题:4.Dubbo源码分析----Reference标签的处理

          本文链接:https://www.haomeiwen.com/subject/jhjwiqtx.html