美文网首页
dubbo 服务订阅

dubbo 服务订阅

作者: skipper_shou | 来源:发表于2020-11-02 21:09 被阅读0次

这里讲的是通过注解@DubboReference来实现服务订阅
我们看源码可以看到ReferenceAnnotationBeanPostProcessor继承AbstractAnnotationBeanPostProcessorAbstractAnnotationBeanPostProcessor继承了InstantiationAwareBeanPostProcessorAdapter.
该后置处理器主要有三个作用:

  • 1.Bean实例化前的一个回调:postProcessBeforeInstantiation。
  • 2.Bean实例化后属性显式填充和自动注入前的回调:postProcessAfterInstantiation
  • 3.给Bean对象属性自动注入的机会:postProcessPropertyValues

可知,被打上@DubboReference 注解的属性值注入,就是利用了这个后置处理器的第三个作用(给Bean对象属性自动注入的机会postProcessPropertyValues)。就是在这个方法内处理Bean对象属性成员的注入。
postProcessPropertyValues通过buildAnnotatedMetadata方法获取AnnotatedFieldElementfindAnnotatedMethodMetadataDubboReference.class, Reference.class, com.alibaba.dubbo.config.annotation.Reference.class数据进行注入,通过getInjectedObject()调用ReferenceAnnotationBeanPostProcessordoGetInjectedBean()创建代理,进行服务订阅

public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBeanPostProcessor implements
        ApplicationContextAware {
    ......
    public ReferenceAnnotationBeanPostProcessor() {
        super(DubboReference.class, Reference.class, com.alibaba.dubbo.config.annotation.Reference.class);
    }

    @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}
         *
         * 得到需要被注入的对象的BeanName,生成规则默认是,查看ServiceBeanNameBuilder.build()
         */
        String referencedBeanName = buildReferencedBeanName(attributes, injectedType);

        /**
         * 得到引用对象@ReferenceBean的BeanName ,
         * 如果有Id 就是Id,没有通过generateReferenceBeanName()产生
         *
         * The name of bean that is declared by {@link Reference @Reference} annotation injection
         */
        String referenceBeanName = getReferenceBeanName(attributes, injectedType);

        //构建一个ReferenceBean 对象,如果不存在的话。
        ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);

        //判断是否为本地ServiceBean,一般都是远程引用dubbo服务。
        boolean localServiceBean = isLocalServiceBean(referencedBeanName, referenceBean, attributes);

        prepareReferenceBean(referencedBeanName, referenceBean, localServiceBean);

        //注册referenceBean
        registerReferenceBean(referencedBeanName, referenceBean, attributes, localServiceBean, injectedType);

        //把referenceBean 放入缓存中。
        cacheInjectedReferenceBean(referenceBean, injectedElement);

        //接着直接通过get()方法来创建一个代理,这get操作就会引入dubbo服务的订阅等相关内容。
        return referenceBean.get();
    }

}
public abstract class AbstractAnnotationBeanPostProcessor extends
        InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered,
        BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean {
    ......
    @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().getSimpleName()
                    + " dependencies is failed", ex);
        }
        return pvs;
    }

    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.
        AbstractAnnotationBeanPostProcessor.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) {
                        throw new IllegalStateException("Failed to introspect object class [" + clazz.getName() +
                                "] for annotation metadata: could not find class that it depends on", err);
                    }
                }
            }
        }
        return metadata;
    }

    private AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata buildAnnotatedMetadata(final Class<?> beanClass) {
        Collection<AbstractAnnotationBeanPostProcessor.AnnotatedFieldElement> fieldElements = findFieldAnnotationMetadata(beanClass);
        Collection<AbstractAnnotationBeanPostProcessor.AnnotatedMethodElement> methodElements = findAnnotatedMethodMetadata(beanClass);
        return new AbstractAnnotationBeanPostProcessor.AnnotatedInjectionMetadata(beanClass, fieldElements, methodElements);
    }

    private class AnnotatedMethodElement extends InjectionMetadata.InjectedElement {

        private final Method method;

        private final AnnotationAttributes attributes;

        private volatile Object object;

        protected AnnotatedMethodElement(Method method, PropertyDescriptor pd, AnnotationAttributes attributes) {
            super(method, pd);
            this.method = method;
            this.attributes = attributes;
        }

        @Override
        protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {

            Class<?> injectedType = pd.getPropertyType();

            Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);

            ReflectionUtils.makeAccessible(method);

            method.invoke(bean, injectedObject);

        }

    }

    public class AnnotatedFieldElement extends InjectionMetadata.InjectedElement {

        private final Field field;

        private final AnnotationAttributes attributes;

        private volatile Object bean;

        protected AnnotatedFieldElement(Field field, AnnotationAttributes attributes) {
            super(field, null);
            this.field = field;
            this.attributes = attributes;
        }

        @Override
        protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {

            Class<?> injectedType = resolveInjectedType(bean, field);

            Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);

            ReflectionUtils.makeAccessible(field);

            field.set(bean, injectedObject);

        }

        private Class<?> resolveInjectedType(Object bean, Field field) {
            Type genericType = field.getGenericType();
            if (genericType instanceof Class) { // Just a normal Class
                return field.getType();
            } else { // GenericType
                return resolveTypeArgument(getTargetClass(bean), field.getDeclaringClass());
            }
        }
    }

protected Object getInjectedObject(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
                                       InjectionMetadata.InjectedElement injectedElement) throws Exception {

        String cacheKey = buildInjectedObjectCacheKey(attributes, bean, beanName, injectedType, injectedElement);

        Object injectedObject = injectedObjectsCache.get(cacheKey);

        if (injectedObject == null) {
            injectedObject = doGetInjectedBean(attributes, bean, beanName, injectedType, injectedElement);
            // Customized inject-object if necessary
            injectedObjectsCache.putIfAbsent(cacheKey, injectedObject);
        }

        return injectedObject;

    }

}

相关文章

  • dubbo 服务订阅

    这里讲的是通过注解@DubboReference来实现服务订阅我们看源码可以看到ReferenceAnnotati...

  • Dubbo 远程服务订阅

    简介 dubbo服务引用有两个时机: Spring 容器调用 ReferenceBean 的 afterPrope...

  • Dubbo Consumer 服务订阅过程

    开篇  整个Dubbo Consumer的引用过程比较复杂,这部分的文章会比较多,这篇文章的目的是描述Consum...

  • springcloud小技能:服务注册&发现如何隔离

    用过dubbo的都知道,dubbo服务发布&订阅有2个重要的参数:version和group。即消费者和生产者不但...

  • zookeeper作为dubbo的服务注册中心

    Dubbo架构图 执行顺序: 0:由Spring容器启动服务. 1 向注册中心注册服务. 2 消费者向注册中心订阅...

  • Dubbo中订阅和通知解析

    Dubbo中关于服务的订阅和通知主要发生在服务提供方暴露服务的过程和服务消费方初始化时候引用服务的过程中。 服务引...

  • Dubbo中订阅和通知解析

    Dubbo中关于服务的订阅和通知主要发生在服务提供方暴露服务的过程和服务消费方初始化时候引用服务的过程中。 服务引...

  • Dubbo

    1、如何自己设计一个类似dubbo的rpc框架? 可以从几方面去思考:1、服务订阅发布(注册中心)2、服务路由3、...

  • Dubbo监控和管理(dubbokeeper)

    dubbo服务原理图: 1. Dubbo服务管理和监控的选择 Dubbo服务的监控官方提供dubbo-mon...

  • Dubbo 服务暴露 总结(五)

    笔记简述Dubbo服务暴露之前分为了两小节Dubbo 服务暴露 源码学习(上)(三) 和Dubbo 服务暴露 源码...

网友评论

      本文标题:dubbo 服务订阅

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