之前看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 方法。继承关系如下:
其构造方法如下:
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 如下:
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); } } }