之前看open远程服务调用的原理是用 FeignClient声明接口,然后用 EnableFeignClients 引入FeignClientsRegistrar,这个内部实际就是注入FeignClientFactoryBean 对象工厂,然后其内部生成的getObject 方法用JDK动态代理生成一个代理对象。代理对象的invoke 方法根据内部维护的Map<Method, MethodHandler> 用反射获取到方法之后进行调用。

  下面研究dubbo的代理对象生成过程以及调用过程。

  我们使用远程dubbo 远程服务的时候是通过注解方式注入一个bean,我们注入的是接口,所以可以猜测dubbo 是采用JDK的动态代理生成代理对象然后返回给容器,然后容器在对象生命周期的属性注入过程中注入到对应的bean 中。

比如:

package cn.qlq.dubbo.controller;

import cn.qz.dubbo.service.UserService;
import cn.qz.dubbo.vo.UserVO;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class UserController {

    @Reference(version = "1.0.0")
    private UserService userService;

    @GetMapping("/listUser")
    public List<UserVO> listUser() {
        return userService.listUser();
    }

    @GetMapping("/addUser")
    public void addUser() {
        UserVO user = new UserVO();
        user.setUsername("addUsername");
        user.setFullname("addFullname");
        user.setAge(25);
        userService.addUser(user);
    }
}

  下面研究其代理创建过程以及调用过程。

1. DubboAutoConfiguration 自动配置引入下面类

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

ReferenceAnnotationBeanPostProcessor 是一个InstantiationAwareBeanPostProcessor, 所以在对象的属性设置过程popluate 方法中会执行其postProcessProperties 方法。继承关系如下:

dubbo源码-服务发现(客户端启动源码)

 其构造方法如下:

    public ReferenceAnnotationBeanPostProcessor() {
        super(Reference.class, com.alibaba.dubbo.config.annotation.Reference.class);
    }

org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationInjectedBeanPostProcessor#AnnotationInjectedBeanPostProcessor:

    private final Class<? extends Annotation>[] annotationTypes;

    public AnnotationInjectedBeanPostProcessor(Class<? extends Annotation>... annotationTypes) {
        Assert.notEmpty(annotationTypes, "The argument of annotations' types must not empty");
        this.annotationTypes = annotationTypes;
    }

2. org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean 属性注入过程中重要代码如下:

        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;
                }
            }
        }

3. 如上代码调用到org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationInjectedBeanPostProcessor#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().getSimpleName()
                    + " dependencies is failed", ex);
        }
        return pvs;
    }

获取到的metadata 如下:

dubbo源码-服务发现(客户端启动源码)

4. 调用到org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement#inject

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

            Class<?> injectedType = field.getType();

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

            ReflectionUtils.makeAccessible(field);

            field.set(bean, injectedObject);

        }

可以看到这里是先获取到需要注入的对象,然后反射进行设置值,所以核心是在获取注入的对象。

5. org.apache.dubbo.config.spring.beans.factory.annotation.AnnotationInjectedBeanPostProcessor#getInjectedObject

   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;

    }

  这里是先从缓存拿,缓存拿不到就调用方法进行load(获取到之后加入缓存)。

cacheKey 如下:

ServiceBean:cn.qz.dubbo.service.UserService:1.0.0#source=private cn.qz.dubbo.service.UserService cn.qlq.dubbo.controller.UserController.userService#attributes={version=1.0.0}

6. org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor#doGetInjectedBean

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

        String referencedBeanName = buildReferencedBeanName(attributes, injectedType);

        ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referencedBeanName, attributes, injectedType);

        registerReferenceBean(referencedBeanName, referenceBean, attributes, injectedType);

        cacheInjectedReferenceBean(referenceBean, injectedElement);

        return buildProxy(referencedBeanName, referenceBean, injectedType);
    }

1》获取referencedBeanName

ServiceBean:cn.qz.dubbo.service.UserService:1.0.0

2》调用buildReferenceBeanIfAbsent 获取ReferenceBean, 这个Bean 可以理解为一个配置bean, 如下:(可以看到由缓存机制,可以确保只有一个相关对象)

    private ReferenceBean buildReferenceBeanIfAbsent(String referencedBeanName, AnnotationAttributes attributes,
                                                     Class<?> referencedType)
            throws Exception {

        ReferenceBean<?> referenceBean = referenceBeanCache.get(referencedBeanName);

        if (referenceBean == null) {
            ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder
                    .create(attributes, applicationContext)
                    .interfaceClass(referencedType);
            referenceBean = beanBuilder.build();
            referenceBeanCache.put(referencedBeanName, referenceBean);
        }

        return referenceBean;
    }

3》registerReferenceBean 将上面的 referenceBean  注册到容器中

    private void registerReferenceBean(String referencedBeanName, ReferenceBean referenceBean,
                                       AnnotationAttributes attributes,
                                       Class<?> interfaceClass) {

        ConfigurableListableBeanFactory beanFactory = getBeanFactory();

        String beanName = getReferenceBeanName(attributes, interfaceClass);

        if (beanFactory.containsBean(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)) {
                beanFactory.registerSingleton(beanName, referenceBean);
            }
        }
    }
View Code

相关文章:

  • 2019-09-29
  • 2021-07-10
  • 2022-12-23
  • 2021-11-29
  • 2021-05-19
  • 2019-09-06
猜你喜欢
  • 2022-01-30
  • 2021-12-27
  • 2021-08-08
  • 2022-12-23
  • 2021-07-06
  • 2021-08-08
  • 2021-05-17
相关资源
相似解决方案