问题:在项目里两次对同一dubbo客户端添加@Reference注解,导致注解属性不起效果。具体demo代码如下:

@Service
public class DemoService1Impl implements DemoService1 {

    @Reference(url = "dubbo://127.0.0.1:12345",validation = "true",timeout = 50000)
    private DemoService demoService;

    @Override
    public void test() {
        demoService.sayHello("aaa");
    }
}

@Service
public class DemoService2Impl implements DemoService2 {

    @Reference(url = "dubbo://127.0.0.1:12345",validation = "false",timeout = 1000000)
    private DemoService demoService;
    
    @Override
    public void test() {
        demoService.sayHello("aaaa");
    }
}

如果先注入了DemoService2Impl这个bean,在DemoService1Impl这个bean中注入的DemoService他的validation的值一直为false,引起原因,在dubbo2.7.3的版本,注入时会从缓存获取,但是缓存的key值是DemoService类的全名,所以导致再次注入时都是第一个注入的配置。好在dubbo的2.7.4版本已经修复该bug。

下面分析dubbo的@Reference注解注入原理:

一、spring的单列创建过程:

Spring下文的刷新方法refresh

@Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {try {// 这里单例的初始化方法入口
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }
        }
    }

 

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// 实例化所有非懒加载单例
        beanFactory.preInstantiateSingletons();
    }

 

 具体实现如下:

@Override
    public void preInstantiateSingletons() throws BeansException {
        //所有的bean
        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
        // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            //如果不是抽象 and 单列 and 非延迟初始化
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                //如果继承FactoryBean的 判断工厂方法是否饥饿加载
                if (isFactoryBean(beanName)) {
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                    if (bean instanceof FactoryBean) {
                        final FactoryBean<?> factory = (FactoryBean<?>) bean;
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                            ((SmartFactoryBean<?>) factory)::isEagerInit,
                                    getAccessControlContext());
                        }
                        else {
                            isEagerInit = (factory instanceof SmartFactoryBean &&
                                    ((SmartFactoryBean<?>) factory).isEagerInit());
                        }
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
                }
                else {
                    //这里真正获取bean
                    getBean(beanName);
                }
            }
        }

        // 主要为调用afterSingletonsInstantiated的单例初始化后的操作
        for (String beanName : beanNames) {
            Object singletonInstance = getSingleton(beanName);
            if (singletonInstance instanceof SmartInitializingSingleton) {
                final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }, getAccessControlContext());
                }
                else {
                    smartSingleton.afterSingletonsInstantiated();
                }
            }
        }
    }

 

然后到getBean方法:

@Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }

    @Override
    public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
        return doGetBean(name, requiredType, null, false);
    }

    @Override
    public Object getBean(String name, Object... args) throws BeansException {
        return doGetBean(name, null, args, false);
    }

 

这里面好几种方式获取bean,真正调用的方法是doGetBean:

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

        final String beanName = transformedBeanName(name);
        Object bean;
        // Eagerly check singleton cache for manually registered singletons.
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {

        }
        else {
            try {


                // 如果是单例
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            //真正创建单例的方法
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
                //多例
                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }
                //其他作用范围
                else {
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }
                    try {
                        Object scopedInstance = scope.get(beanName, () -> {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        throw new BeanCreationException(beanName,
                                "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                ex);
                    }
                }
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }
        return (T) bean;
    }

 

这个方法看起来很复杂,最后真正创建的方法是AbstractAutowireCapableBeanFactory的createBean方法:

@Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {
        //执行postProcessBeforeInstantiation的地方
        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        
        try {
            //真正创建bean地方
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isTraceEnabled()) {
                logger.trace("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
    }

 

上面我们用到的很多bean做拓展的地方resolveBeforeInstantiation这个方法:

@Nullable
    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            // Make sure bean class is actually resolved at this point.
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }
    
    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                if (result != null) {
                    return result;
                }
            }
        }
        return null;
    }

 

获得注入的所有实现BeanPostProcessor接口的bean,依次调用。然后我们看真正创建bean的方法doCreateBean:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {
        //真正创建bean对象,并使用BeanWrapper包装
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    //这里是依次调用MergedBeanDefinitionPostProcessor的方法
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }


        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            //填充bean的所有属性
            populateBean(beanName, mbd, instanceWrapper);
            //初始化bean
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }

 

然后我们先分析populateBean方法:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {

        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);


        PropertyDescriptor[] filteredPds = null;
        if (hasInstAwareBpps) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        if (filteredPds == null) {
                            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                        }
                        //真正设置属性值的方法
                        pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvsToUse == null) {
                            return;
                        }
                    }
                    pvs = pvsToUse;
                }
            }
        }
    }

 

这个方法很复杂,最后真正对属性赋值的是查找到所有继承InstantiationAwareBeanPostProcessor的bean 然后依次调用postProcessPropertyValues方法,而这里恰好就是dubbo拓展了的地方。

二、dubbo的@Refrence的注入过程:

在dubbo的自动配置DubboAutoConfiguration类中注入了:

@ConditionalOnMissingBean
    @Bean(name = ReferenceAnnotationBeanPostProcessor.BEAN_NAME)
    public ReferenceAnnotationBeanPostProcessor referenceAnnotationBeanPostProcessor() {
        return new ReferenceAnnotationBeanPostProcessor();
    }

 

ReferenceAnnotationBeanPostProcessor 这个类继承了AnnotationInjectedBeanPostProcessor,而AnnotationInjectedBeanPostProcessor最终实现了InstantiationAwareBeanPostProcessor的postProcessPropertyValues方法:
在AnnotationInjectedBeanPostProcessor类中有如下方法:
@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;
    }

 

最后调用了AnnotatedFieldElement的inject方法:
·@Override
        protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {

            Class<?> injectedType = field.getType();
            //获取dubbo生成的代理对象
            Object injectedObject = getInjectedObject(attributes, bean, beanName, injectedType, this);
            ReflectionUtils.makeAccessible(field);
            //设置到DemoService1Impl的demoService字段上
            field.set(bean, injectedObject);

        }

 

 

生成dubbo代理对象的核心方法getInjectedObject如下:
protected Object getInjectedObject(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
                                       InjectionMetadata.InjectedElement injectedElement) throws Exception {
        //创建dubbo对象的缓存key
        //最终生成的key="ServiceBean:com.donny.DemoService#source=private com.donny.DemoService com.donny.DemoService1Impl.demoService#attributes={timeout=50000, url=dubbo://127.0.0.1:12345, validation=true}"
        String cacheKey = buildInjectedObjectCacheKey(attributes, bean, beanName, injectedType, injectedElement);
        //缓存中是否存在
        Object injectedObject = injectedObjectsCache.get(cacheKey);

        if (injectedObject == null) {
            //真正获取dubbo代理对象的方法
            injectedObject = doGetInjectedBean(attributes, bean, beanName, injectedType, injectedElement);
            // Customized inject-object if necessary
            injectedObjectsCache.putIfAbsent(cacheKey, injectedObject);
        }

        return injectedObject;

    }

 

然后我们去到了ReferenceAnnotationBeanPostProcessor的doGetInjectedBean方法:
@Override
    protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
                                       InjectionMetadata.InjectedElement injectedElement) throws Exception {

        //referencedBeanName="ServiceBean:com.donny.DemoService"
        String referencedBeanName = buildReferencedBeanName(attributes, injectedType);
        //referenceBeanName="@Reference(timeout=50000,url=dubbo://127.0.0.1:12345,validation=true) com.donny.DemoService"
        //这个是在2.7.4新加的名称,为了区分不同配置的@Refrence注解创建不同的实例
        String referenceBeanName = getReferenceBeanName(attributes, injectedType);
        //在2.7.3 buildReferenceBeanIfAbsent()传的是referencedBeanName
        //创建dubbo的客户端ReferenceBean
        ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);
        //注册ReferenceBean到工厂
        registerReferenceBean(referencedBeanName, referenceBean, attributes, injectedType);

        cacheInjectedReferenceBean(referenceBean, injectedElement);
        //创建dubbo的客户端代理bean
        return getOrCreateProxy(referencedBeanName, referenceBeanName, referenceBean, injectedType);
    }

 

然后我们再看下registerReferenceBean方法:
private void registerReferenceBean(String referencedBeanName, ReferenceBean referenceBean,
                                       AnnotationAttributes attributes,
                                       Class<?> interfaceClass) {

        ConfigurableListableBeanFactory beanFactory = getBeanFactory();

        String beanName = getReferenceBeanName(attributes, interfaceClass);

        if (existsServiceBean(referencedBeanName)) { // 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)) {
                //最终注册到spring,beanName=“@Reference(timeout=50000,url=dubbo://127.0.0.1:12345,validation=true) com.donny.DemoService”
                beanFactory.registerSingleton(beanName, referenceBean);
            }
        }
    }

 

ReferenceBean包含了dubbo客户端的所有配置信息
由上可以总结出:dubbo的ReferenceBean会注册到spring,而dubbo的客户端代理bean不会注册到spring(使用@MockBean单元测试时dubbo客户端不能mock也是这个原因,只能手工mock后赋值),只是在创建spring的bean时通过属性设置上去。