一、现象说明
- 在单使用spring的时候,controller 会在 运行期 根据 泛型依赖注入 相应的 service;
- 使用dubbo拆分时,controller 层只会注入BaseService的实体,而本案例BaseService为abstract类型,dubbo provider端 初始化时并不会在zookeeper中注册,以至于 consumer端 生成不了 相应的proxyObject。
二、案例代码结构
1.service 层, 在provider端
2.controller 层,在consumer 端
三、断点跟进
1.dubbo初始化 会将 对象放入 ReferenceAnnotationBeanPostProcessor类中的 HashMap类型的 injectionMetadataCache缓存起来
ReferenceAnnotationBeanPostProcessor.postProcessMergedBeanDefinition() --> findReferenceMetadata(){ ... metadata = buildReferenceMetadata(clazz); // 构建元数据 this.injectionMetadataCache.put(cacheKey, metadata); // 放入injectionMetadataCache对象中 .. } -->
- 停在要找的userController ,看一下 metadata 怎么生成的?
//跟进buildReferenceMetadata方法 private ReferenceInjectionMetadata buildReferenceMetadata(final Class<?> beanClass) { // 利用spring的RefelectUtils获取Field,Method Collection<ReferenceFieldElement> fieldElements = findFieldReferenceMetadata(beanClass); Collection<ReferenceMethodElement> methodElements = findMethodReferenceMetadata(beanClass); return new ReferenceInjectionMetadata(beanClass, fieldElements, methodElements); }
-->跟进 findFieldReferenceMetadata() 方法
- 看一下field 是下面个东西
2.dubbo被调用,也就是userController 实例化 执行 populateBean 给属性 baseService 赋值的时候。
- 会有很多beanPostProcessor 进行前置处理
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); } // 找到ReferenceAnnotationBeanPostProcessor 跟进 pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } }
- 找到ReferenceAnnotationBeanPostProcessor 跟进 postProcessPropertyValues
@Override public PropertyValues postProcessPropertyValues( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException { //因为 InjectionMetadata 被初始化过了,所以是直接从缓存 injectionMetadataCache 对象中取到 InjectionMetadata metadata = findReferenceMetadata(beanName, bean.getClass(), pvs); try { // 关键方法,会生成baseService的代理对象然后注入到bean里,有兴趣的可以继续跟进一下。 metadata.inject(bean, beanName, pvs); } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of @Reference dependencies failed", ex); } return pvs; }
- 最后会生成这样的代理对象,并不是想要的userService的代理对象。