Spring整合Dubbo中@Reference注解解析原理
@Reference: 可以用在属性或者方法, 意味着需要引用某个Dubbo服务, 那么Dubbo整合Spring后, 我很好奇怎么把这个过程完成的。
package org.apache.dubbo.demo.provider;publicclassApplication{publicstaticvoidmain(String[] args)throws Exception {
AnnotationConfigApplicationContext context =newAnnotationConfigApplicationContext(ProviderConfiguration.class);
context.start();
System.in.read();}@Configuration@EnableDubbo(scanBasePackages ="org.apache.dubbo.demo.provider")@PropertySource("classpath:/spring/dubbo-provider.properties")staticclassProviderConfiguration{}}//@EnabeDubbo注解@EnableDubboConfig@DubboComponentScanpublic @interfaceEnableDubbo{//该属性的值也是DubboComponentScan属性basePackages的值;@AliasFor(annotation = DubboComponentScan.class, attribute ="basePackages")
String[]scanBasePackages()default{};@AliasFor(annotation = DubboComponentScan.class, attribute ="basePackageClasses")
Class<?>[]scanBasePackageClasses()default{};@AliasFor(annotation = EnableDubboConfig.class, attribute ="multiple")booleanmultipleConfig()defaulttrue;}
- @DubboComponentScan: 用来扫描@Service 和@Reference注解修饰的类;
DubboComponentScanRegistrar
publicclassDubboComponentScanRegistrarimplementsImportBeanDefinitionRegistrar{@OverridepublicvoidregisterBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){
System.out.println("执行DubboComponentScanRegistrar");// 拿到DubboComponentScan注解所定义的包路径,扫描该package下的类,识别这些类上
Set<String> packagesToScan =getPackagesToScan(importingClassMetadata);// 注册ServiceAnnotationBeanPostProcessor一个Bean// 实现了BeanDefinitionRegistryPostProcessor接口,所以在Spring启动时会调用postProcessBeanDefinitionRegistry方法// 该方法会进行扫描,扫描@Service注解了的类,然后生成BeanDefinition(会生成两个,一个普通的bean,一个ServiceBean),后续的Spring周期中会生成Bean// 在ServiceBean中会监听ContextRefreshedEvent事件,一旦Spring启动完后,就会进行服务导出registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);// 注册ReferenceAnnotationBeanPostProcessor// 实现了AnnotationInjectedBeanPostProcessor接口,继而实现了InstantiationAwareBeanPostProcessorAdapter接口// 所以Spring在启动时,在对属性进行注入时会调用AnnotationInjectedBeanPostProcessor接口中的postProcessPropertyValues方法// 在这个过程中会按照@Refrence注解的信息去生成一个RefrenceBean对象registerReferenceAnnotationBeanPostProcessor(registry);}}
- registerServiceAnnotationBeanPostProcessor方法用来解析@Service注解修饰的类, 最后会获得一个服务实现类, 一个ServiceBean类注入容器;
- registerReferenceAnnotationBeanPostProcessor: 是用来解析@Reference注解的方法;
registerReferenceAnnotationBeanPostProcessor(registry)
/**
* Registers {@link ReferenceAnnotationBeanPostProcessor} into {@link BeanFactory}
*
* @param registry {@link BeanDefinitionRegistry}
*/privatevoidregisterReferenceAnnotationBeanPostProcessor(BeanDefinitionRegistry registry){// Register @Reference Annotation Bean Processor// 注册一个ReferenceAnnotationBeanPostProcessor做为bean,ReferenceAnnotationBeanPostProcessor是一个BeanPostProcessor
BeanRegistrar.registerInfrastructureBean(registry,
ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class);}
工作:
- 判断容器中是否包含了referenceAnnotationBeanPostProcessor名称的Bean,如果有,结束;
- 根据Bean的类型ReferenceAnnotationBeanPostProcessor.class,创建一个RootBeanDefinition实例;
- 设置Role属性;
- 注入容器中;
publicclassBeanRegistrar{/**
* Register Infrastructure Bean
*
* @param beanDefinitionRegistry {@link BeanDefinitionRegistry}
* @param beanType the type of bean
* @param beanName the name of bean
*/publicstaticvoidregisterInfrastructureBean(BeanDefinitionRegistry beanDefinitionRegistry,
String beanName,
Class<?> beanType){if(!beanDefinitionRegistry.containsBeanDefinition(beanName)){
RootBeanDefinition beanDefinition =newRootBeanDefinition(beanType);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);}}}
ReferenceAnnotationBeanPostProcessor
- 继承了AnnotationInjectedBeanPostProcessor类,该类又继承了MergedBeanDefinitionPostProcessor,InstantiationAwareBeanPostProcessorAdapter 类;
- 应用启动的时候, 对于我们引入服务的类, Spring会进行对这些类进行依赖注入(类似@Autowired)
- 依赖注入的时候会调用AnnotationInjectedBeanPostProcessor#postProcessPropertyValues()方法,这个方法里面使用了子类的处理逻辑,按照子类的处理逻辑进行依赖注入;
- 在依赖注入前,会先执行MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法, 子类AnnotationInjectedBeanPostProcessor实现了这个接口, 目的是扫描所有被@Reference注解修饰的方法和属性的准备工作;
publicclassReferenceAnnotationBeanPostProcessorextendsAnnotationInjectedBeanPostProcessorimplementsApplicationContextAware, ApplicationListener {//...}publicabstractclassAnnotationInjectedBeanPostProcessorextendsInstantiationAwareBeanPostProcessorAdapterimplementsMergedBeanDefinitionPostProcessor, PriorityOrdered,
BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean {//...}publicabstractclassInstantiationAwareBeanPostProcessorAdapterimplementsSmartInstantiationAwareBeanPostProcessor{//....@Overridepublic PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)throws BeansException {return pvs;}}
MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法
由子类AnnotationInjectedBeanPostProcessor 实现了这个方法;
publicinterfaceMergedBeanDefinitionPostProcessorextendsBeanPostProcessorvoidpostProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);}publicabstractclassAnnotationInjectedBeanPostProcessorextendsInstantiationAwareBeanPostProcessorAdapterimplementsMergedBeanDefinitionPostProcessor, PriorityOrdered,
BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean {//...@OverridepublicvoidpostProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName){if(beanType != null){
InjectionMetadata metadata =findInjectionMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);}}}
一、findInjectionMetadata(beanName, beanType, null)
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.
AnnotationInjectedBeanPostProcessor.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){//...}}}return metadata;}
- 这些元数据是通过反射获取的,由于反射本身性能不高,所以拿到一些元数据后,需要放入本地缓存injectionMetadataCache中,下次直接从缓存中获取;
- 扫描 @Reference修饰的属性或者方法,对应类型为AnnotatedFieldElement, AnnotatedMethodElement
- injectionMetadataCache缓存 的 key为 bean的名称,或者类的名称, 值的类型AnnotatedInjectionMetadata;
- AnnotatedInjectionMetadata里面包装两个集合, 被@reference修饰的属性集合, 被@Reference修饰的方法集合
buildAnnotatedMetadata(clazz)
工作:
- 获取哪些Filed上有@Reference注解
- 获取哪些方法上有@Reference注解
- 创建一个AnnotatedInjectionMetadata实例, 参数是属性和方法集合, 属性注入会按照这个类去进行的;返回实例;
private AnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata buildAnnotatedMetadata(final Class<?> beanClass){// 扫描Field
Collection<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> fieldElements =findFieldAnnotationMetadata(beanClass);// 扫描Method
Collection<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> methodElements =findAnnotatedMethodMetadata(beanClass);// 返回的是Dubbo定义的AnnotatedInjectionMetadata,接下来就会使用这个类去进行属性注入returnnewAnnotationInjectedBeanPostProcessor.AnnotatedInjectionMetadata(beanClass, fieldElements, methodElements);}
- 扫描Field 工作:
- 创建结果集合List;
- 遍历beanClass的所有的Field;
- 获取Feild上所有的注解;
- getMergedAttributes获取@Reference注解, 如果不存在,返回空;
- 存在@Reference注解,就会获取@reference注解的所有属性,AnnotationAttributes 存储就是注解的属性信息;
- 存在Reference注解,就加入集合List;
private List<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement>findFieldAnnotationMetadata(final Class<?> beanClass){final List<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement> elements =newLinkedList<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement>();
ReflectionUtils.doWithFields(beanClass, field ->{for(Class<?extendsAnnotation> annotationType :getAnnotationTypes()){
AnnotationAttributes attributes =getMergedAttributes(field, annotationType,getEnvironment(),true);if(attributes != null){//...
elements.add(newAnnotatedFieldElement(field, attributes));}}});return elements;}
- 扫描Method 工作:
- 创建结果集合List
- 获取beanClass所有的Method属性
- 获取所有修饰Method属性的注解,遍历
- getMergedAttributes判断Method是否被@Reference注解修饰,有则获取注解的所有信息;
- 找到set方法所对应的属性;
- 加入结果集合List
private List<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement>findAnnotatedMethodMetadata(final Class<?> beanClass){final List<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement> elements =newLinkedList<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement>();
ReflectionUtils.doWithMethods(beanClass, method ->{
Method bridgedMethod =findBridgedMethod(method);for(Class<?extendsAnnotation> annotationType :getAnnotationTypes()){
AnnotationAttributes attributes =getMergedAttributes(bridgedMethod, annotationType,getEnvironment(),true);if(attributes != null && method.equals(ClassUtils.getMostSpecificMethod(method, beanClass))){//....// 找到set方法所对应的属性
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, beanClass);
elements.add(newAnnotatedMethodElement(method, pd, attributes));}}});return elements;}
获取完之后, 退出, 返回AnnotatedInjectionMetadata到(一)步骤中的调用处,然后会将这些Field和Method信息放入缓存;
postProcessPropertyValues
InstantiationAwareBeanPostProcessorAdapter抽象类已经定义好了该方法,子类AnnotationInjectedBeanPostProcessor 重写该方法,进行@Reference的依赖注入过程;
publicabstractclassInstantiationAwareBeanPostProcessorAdapterimplementsSmartInstantiationAwareBeanPostProcessor{@Overridepublic PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)throws BeansException {return pvs;}}}publicabstractclassAnnotationInjectedBeanPostProcessorextendsInstantiationAwareBeanPostProcessorAdapterimplementsMergedBeanDefinitionPostProcessor, PriorityOrdered,
BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean {@Overridepublic PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)throws BeanCreationException {// 寻找需要注入的属性(被@Reference标注的Field)
InjectionMetadata metadata =findInjectionMetadata(beanName, bean.getClass(), pvs);try{
metadata.inject(bean, beanName, pvs);}catch(Exception e){//..异常处理}return pvs;}}
工作:
- 先获取代表@Reference修饰的Field和Method信息类;在(一)步骤中,已经扫描完成,放入缓存,因此只需要先从缓存中获取;
- 执行属性注入;
InjectionMetadata#inject(Object target, String beanName, PropertyValues pvs)
作用: 执行属性注入
工作:
- 先获取被@Reference修饰的属性集合injectedElements;
- 遍历集合injectedElements
- 执行属性注入;
publicvoidinject(Object target, String beanName, PropertyValues pvs)throws Throwable {
Collection<InjectedElement> elementsToIterate =(this.checkedElements != null ?this.checkedElements :this.injectedElements);if(!elementsToIterate.isEmpty()){boolean debug = logger.isDebugEnabled();for(InjectedElement element : elementsToIterate){if(debug){
logger.debug("Processing injected element of bean '"+ beanName +"': "+ element);}
element.inject(target, beanName, pvs);}}}
AnnotatedFieldElement#inject(target, beanName, pvs)
- InjectedElement 是 InjectionMetadata内部类,定义了inject方法, 但是代表被@Reference修饰的属性的类是AnnotatedFieldElement
- 该类继承了InjectedElement ,重写了inject方法, 因此调用InjectedElement 其实就是调用AnnotatedFieldElement的inject方法
publicclassAnnotatedFieldElementextendsInjectionMetadata.InjectedElement{}
inject工作:
- 获取Field的类型;
- 获取对象getInjectedObject
- 设置为可访问
- 反射给Field设值;
@Overrideprotectedvoidinject(Object bean, String beanName, PropertyValues pvs)throws Throwable {// 给bean对象进行属性赋值
Class<?> injectedType = field.getType();// 获取对象,然后进行注入
Object injectedObject =getInjectedObject(attributes, bean, beanName, injectedType,this);
ReflectionUtils.makeAccessible(field);// 字段赋值,injectedObject就是值
field.set(bean, injectedObject);}
AnnotationInjectedBeanPostProcessor#getInjectedObject方法
获取注入属性实例;
工作:
- buildInjectedObjectCacheKey()生成注入对象的缓存key;
- 从缓存中获取 属性注入的实例;
- 如果存在, 直接返回;
- 如果不能存在, 生成属性注入的实例;
- 放入缓存中;
protected Object getInjectedObject(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
InjectionMetadata.InjectedElement injectedElement)throws Exception {// ServiceBean:org.apache.dubbo.demo.DemoService#source=private org.apache.dubbo.demo.DemoService org.apache.dubbo.demo.consumer.comp.DemoServiceComponent.demoService#attributes={parameters=[Ljava.lang.String;@42e25b0b}// 哪个Service应用了哪个类型的服务,通过什么方式引入的
String cacheKey =buildInjectedObjectCacheKey(attributes, bean, beanName, injectedType, injectedElement);// cacheKey很鸡肋,属性名不一样的时候,cacheKey不一样,导致不能缓存, 在一个Service中@Reference两次同一个服务缓存不到
Object injectedObject = injectedObjectsCache.get(cacheKey);if(injectedObject == null){// 生成Bean
injectedObject =doGetInjectedBean(attributes, bean, beanName, injectedType, injectedElement);// Customized inject-object if necessary
injectedObjectsCache.putIfAbsent(cacheKey, injectedObject);}return injectedObject;}
ReferenceAnnotationBeanPostProcessor#doGetInjectedBean
参数:
- attributes: 代表@Reference注解的所有配置的属性信息;
- bean : 代表执行属性注入的类Bean实例;
- beanName: 代表执行属性注入的类Bean实例的名称;
- injectedType : 待注入的属性类型;
工作:
- 获取该属性注入的服务Bean的名称referencedBeanName ;
- 获取referencedBeanName属性;
- buildReferenceBeanIfAbsent生成一个ReferenceBean 对象;
- registerReferenceBean 注入到Spring容器中, 这样就可以在其他地方就可以使用@Autowired注解自动注入;
- cacheInjectedReferenceBean-缓存bean实例;
- getOrCreateProxy - 创建一个代理对象返回;也就是意味着,最后注入的属性是一个代理对象;
@Overrideprotected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
InjectionMetadata.InjectedElement injectedElement)throws Exception {//该属性注入的服务Bean的名称referencedBeanName
String referencedBeanName =buildReferencedBeanName(attributes, injectedType);/**
* The name of bean that is declared by {@link Reference @Reference} annotation injection
*/// @Reference(methods=[Lorg.apache.dubbo.config.annotation.Method;@39b43d60) org.apache.dubbo.demo.DemoService// 我要生成一个RefrenceBean,对应的beanName, 根据@Reference注解来标识不同
String referenceBeanName =getReferenceBeanName(attributes, injectedType);// 生成一个ReferenceBean对象
ReferenceBean referenceBean =buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);// 把referenceBean添加到Spring容器中去registerReferenceBean(referencedBeanName, referenceBean, attributes, injectedType);//缓存cacheInjectedReferenceBean(referenceBean, injectedElement);// 创建一个代理对象,Service中的属性被注入的就是这个代理对象// 内部会调用referenceBean.get();returngetOrCreateProxy(referencedBeanName, referenceBeanName, referenceBean, injectedType);}
ReferenceAnnotationBeanPostProcessor#buildReferencedBeanName
创建一个ReferencedBeanName字符串;
工作:
- 创建一个ServiceBeanNameBuilder构建者对象, 传入@Reference注解信息, 注入的服务类型,环境信息;
- 生成ReferencedBeanName字符串;
- 该名称是以 注入服务接口类名 + 版本号 + 分组名称 格式生成的;
- 如: ServiceBean:org.apache.dubbo.demo.DemoService 表示得到该服务Bean的beanName
private String buildReferencedBeanName(AnnotationAttributes attributes, Class<?> serviceInterfaceType){
ServiceBeanNameBuilder serviceBeanNameBuilder =create(attributes, serviceInterfaceType,getEnvironment());return serviceBeanNameBuilder.build();}// ServiceBeanNameBuilder # builder()public String build(){
StringBuilder beanNameBuilder =newStringBuilder("ServiceBean");// Requiredappend(beanNameBuilder, interfaceClassName);// Optionalappend(beanNameBuilder, version);append(beanNameBuilder, group);// Build and remove last ":"
String rawBeanName = beanNameBuilder.toString();// Resolve placeholdersreturn environment.resolvePlaceholders(rawBeanName);}
ReferenceAnnotationBeanPostProcessor#getReferenceBeanName
获取ReferenceBeanName名称字符串;
工作:
- 获取注解信息中的id属性;
- 判断id是否为空,为空 ;generateReferenceBeanName生成一个ReferenceBeanName字符串;
- 返回
private String getReferenceBeanName(AnnotationAttributes attributes, Class<?> interfaceClass){// id attribute appears since 2.7.3
String beanName =getAttribute(attributes,"id");// beanName为null时会进入if判断if(!hasText(beanName)){
beanName =generateReferenceBeanName(attributes, interfaceClass);}return beanName;}
generateReferenceBeanName生成一个ReferenceBeanName字符串;
工作:
- 获取@Reference注解信息所有属性项;
- 遍历属性项, 每个配置项以 “key = value ”的形式插入构造器字符串;
- 插入属性接口类型名称;
- 返回生成的ReferenceBeanName名称;
private String generateReferenceBeanName(AnnotationAttributes attributes, Class<?> interfaceClass){
StringBuilder beanNameBuilder =newStringBuilder("@Reference");if(!attributes.isEmpty()){
beanNameBuilder.append('(');for(Map.Entry<String, Object> entry : attributes.entrySet()){
beanNameBuilder.append(entry.getKey()).append('=').append(entry.getValue()).append(',');}// replace the latest "," to be ")"
beanNameBuilder.setCharAt(beanNameBuilder.lastIndexOf(","),')');}
beanNameBuilder.append(" ").append(interfaceClass.getName());return beanNameBuilder.toString();}
referenceBeanName与referencedBeanName的区别
前者以 接口类路径名 + 版本号 + 组名 创建的;
后者以 注解所有信息 + 属性接口类型 创建的;
buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType)
目的: 创建一个ReferenceBean对象实例;
工作 :
- 根据生成的referenceBeanName从缓存referenceBeanCache中获取ReferenceBean实例;
- 存在, 直接返回
- 不存在,调用ReferenceBeanBuilder#build()方法就创建一个ReferenceBean对象;
- 不存在, 创建完Reference实例后, 放入缓存中;
- 返回;
private ReferenceBean buildReferenceBeanIfAbsent(String referenceBeanName, AnnotationAttributes attributes, Class<?> referencedType)throws Exception {
ReferenceBean<?> referenceBean = referenceBeanCache.get(referenceBeanName);if(referenceBean == null){// 生成了一个ReferenceBean对象,attributes是@Reference注解的参数值
ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder
.create(attributes, applicationContext).interfaceClass(referencedType);
referenceBean = beanBuilder.build();
referenceBeanCache.put(referenceBeanName, referenceBean);}elseif(!referencedType.isAssignableFrom(referenceBean.getInterfaceClass())){//...}return referenceBean;}
ReferenceBeanBuilder#build()
创建一个Reference对象;
工作:
- 创建一个ReferenceBean对象
- 给ReferenceBean对象的属性赋值
publicfinal C build()throws Exception {checkDependencies();
C configBean =doBuild();configureBean(configBean);//....return configBean;}
configureBean(C configBean)
作用: 设置ReferenceBean的属性;
工作:
- @Reference注解中的配置项赋值给configBean
- 配置注册中心;
- 配置监控中心;
- 配置Dubbo应用配置;
- 配置模块信息;
- 还是配置属性信息;
protectedvoidconfigureBean(C configBean)throws Exception {// preConfigureBean(attributes, configBean);configureRegistryConfigs(configBean);configureMonitorConfig(configBean);configureApplicationConfig(configBean);configureModuleConfig(configBean);// 设置applicationContext、interfaceName、consumer、methods属性,并调用ReferenceBean对象的afterPropertiesSet方法postConfigureBean(attributes, configBean);}//工作流程//1.创建数据绑定器, 这个是Spring的内容数据绑定技术;//2. 去空格;//3. 解析并设置parameter参数;//4. 使用数据绑定技术, 将@Reference的基本数据设置给ReferenceBean;@OverrideprotectedvoidpreConfigureBean(AnnotationAttributes attributes, ReferenceBean referenceBean){
DataBinder dataBinder =newDataBinder(referenceBean);// Register CustomEditors for special fields// 去掉空格
dataBinder.registerCustomEditor(String.class,"filter",newStringTrimmerEditor(true));
dataBinder.registerCustomEditor(String.class,"listener",newStringTrimmerEditor(true));// 你可以这么配@Reference(parameters = {"text=123"})// 也可以这么配@Reference(parameters = {"text:123"})// 最终都会转变为Map设置到referenceBean中的parameters
dataBinder.registerCustomEditor(Map.class,"parameters",newPropertyEditorSupport(){@OverridepublicvoidsetAsText(String text)throws java.lang.IllegalArgumentException {// Trim all whitespace
String content = StringUtils.trimAllWhitespace(text);if(!StringUtils.hasText(content)){// No content , ignore directlyreturn;}// replace "=" to ","
content = StringUtils.replace(content,"=",",");// replace ":" to ","
content = StringUtils.replace(content,":",",");// String[] to Map
Map<String, String> parameters = CollectionUtils.toStringMap(commaDelimitedListToStringArray(content));setValue(parameters);}});
dataBinder.bind(newAnnotationPropertyValuesAdapter(attributes, applicationContext.getEnvironment(), IGNORE_FIELD_NAMES));}//工作流程://1. 设置上下文ApplicationContext;//2. 设置接口;//3. 设置ConsumerConfig配置; 对应的是 注解里面设置 的consumer 配置信息;//4. 设置Methodconfig配置//4. 调用afterPropertiesSet(), 还是设置属性星系;@OverrideprotectedvoidpostConfigureBean(AnnotationAttributes attributes, ReferenceBean bean)throws Exception {
bean.setApplicationContext(applicationContext);configureInterface(attributes, bean);configureConsumerConfig(attributes, bean);configureMethodConfig(attributes, bean);
bean.afterPropertiesSet();}publicvoidafterPropertiesSet()throws Exception {// 这个方法还是在给ReferenceBean对象的属性赋值if(applicationContext != null){
BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ConfigCenterBean.class,false,false);}// 如果@Reference注解中没有配置consumer参数if(getConsumer()== null){// 那么则从Spring容器中寻找ConsumerConfig类型的Bean, 比如通过@Bean定义了一个ConsumerConfig的Bean
Map<String, ConsumerConfig> consumerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class,false,false);if(consumerConfigMap != null && consumerConfigMap.size()>0){
ConsumerConfig consumerConfig = null;// 可能存在多个ConsumerConfig类型的Bean,遍历这些Bean,取第一个没有配置default或者default为true的Bean作为consumer的值for(ConsumerConfig config : consumerConfigMap.values()){if(config.isDefault()== null || config.isDefault()){if(consumerConfig != null){thrownewIllegalStateException("Duplicate consumer configs: "+ consumerConfig +" and "+ config);}
consumerConfig = config;}}if(consumerConfig != null){setConsumer(consumerConfig);}}}if(getApplication()== null
&&(getConsumer()== null ||getConsumer().getApplication()== null)){
Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class,false,false);if(applicationConfigMap != null && applicationConfigMap.size()>0){
ApplicationConfig applicationConfig = null;for(ApplicationConfig config : applicationConfigMap.values()){if(applicationConfig != null){thrownewIllegalStateException("Duplicate application configs: "+ applicationConfig +" and "+ config);}
applicationConfig = config;}if(applicationConfig != null){setApplication(applicationConfig);}}}if(getModule()== null
&&(getConsumer()== null ||getConsumer().getModule()== null)){
Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class,false,false);if(moduleConfigMap != null && moduleConfigMap.size()>0){
ModuleConfig moduleConfig = null;for(ModuleConfig config : moduleConfigMap.values()){if(config.isDefault()== null || config.isDefault()){if(moduleConfig != null){thrownewIllegalStateException("Duplicate module configs: "+ moduleConfig +" and "+ config);}
moduleConfig = config;}}if(moduleConfig != null){setModule(moduleConfig);}}}// 如果@Reference注解上没有配置registryIds// 那么则看application或consumer上有没有配置registryIdsif(StringUtils.isEmpty(getRegistryIds())){if(getApplication()!= null && StringUtils.isNotEmpty(getApplication().getRegistryIds())){setRegistryIds(getApplication().getRegistryIds());}if(getConsumer()!= null && StringUtils.isNotEmpty(getConsumer().getRegistryIds())){setRegistryIds(getConsumer().getRegistryIds());}}if(CollectionUtils.isEmpty(getRegistries())&&(getConsumer()== null || CollectionUtils.isEmpty(getConsumer().getRegistries()))&&(getApplication()== null || CollectionUtils.isEmpty(getApplication().getRegistries()))){
Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class,false,false);if(registryConfigMap != null && registryConfigMap.size()>0){
List<RegistryConfig> registryConfigs =newArrayList<>();if(StringUtils.isNotEmpty(registryIds)){
Arrays.stream(COMMA_SPLIT_PATTERN.split(registryIds)).forEach(id ->{if(registryConfigMap.containsKey(id)){
registryConfigs.add(registryConfigMap.get(id));}});}if(registryConfigs.isEmpty()){for(RegistryConfig config : registryConfigMap.values()){if(StringUtils.isEmpty(registryIds)){
registryConfigs.add(config);}}}if(!registryConfigs.isEmpty()){super.setRegistries(registryConfigs);}}}if(getMetadataReportConfig()== null){
Map<String, MetadataReportConfig> metadataReportConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MetadataReportConfig.class,false,false);if(metadataReportConfigMap != null && metadataReportConfigMap.size()==1){// first elementssuper.setMetadataReportConfig(metadataReportConfigMap.values().iterator().next());}elseif(metadataReportConfigMap != null && metadataReportConfigMap.size()>1){thrownewIllegalStateException("Multiple MetadataReport configs: "+ metadataReportConfigMap);}}// 如果@Reference注解中没有配置configCenter属性// 那么则从Spring容器中找ConfigCenterConfig类型的beanif(getConfigCenter()== null){
Map<String, ConfigCenterConfig> configenterMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ConfigCenterConfig.class,false,false);// 只能配一个ConfigCenterConfigif(configenterMap != null && configenterMap.size()==1){// 设置进去super.setConfigCenter(configenterMap.values().iterator().next());}elseif(configenterMap != null && configenterMap.size()>1){thrownewIllegalStateException("Multiple ConfigCenter found:"+ configenterMap);}}if(getMonitor()== null
&&(getConsumer()== null ||getConsumer().getMonitor()== null)&&(getApplication()== null ||getApplication().getMonitor()== null)){
Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class,false,false);if(monitorConfigMap != null && monitorConfigMap.size()>0){
MonitorConfig monitorConfig = null;for(MonitorConfig config : monitorConfigMap.values()){if(config.isDefault()== null || config.isDefault()){if(monitorConfig != null){thrownewIllegalStateException("Duplicate monitor configs: "+ monitorConfig +" and "+ config);}
monitorConfig = config;}}if(monitorConfig != null){setMonitor(monitorConfig);}}}if(getMetrics()== null){
Map<String, MetricsConfig> metricsConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MetricsConfig.class,false,false);if(metricsConfigMap != null && metricsConfigMap.size()>0){
MetricsConfig metricsConfig = null;for(MetricsConfig config : metricsConfigMap.values()){if(metricsConfig != null){thrownewIllegalStateException("Duplicate metrics configs: "+ metricsConfig +" and "+ config);}
metricsConfig = config;}if(metricsConfig != null){setMetrics(metricsConfig);}}}if(shouldInit()){getObject();}}
registerReferenceBean(referencedBeanName, referenceBean, attributes, injectedType)
目的:将ReferenceBean注入容器, 这个步骤中,会将服务实现类注入容器,这样一个地方使用@Reference注解后,其他地方就可以通过@Autowired自动注入了。
工作:
- 获取Bean工厂;
- 获取referenceBeanName字符串, 将@Reference注解内容以键值对拼接 + 服务接口名; (应该是重复操作了)
- 判断容器是否已经存在这个Bean了。如果存在,则是本地服务(@Service注解修饰的服务在@Reference注解之前解析完成了)
- 存在的话,则根据referenceBeanName去BeanFactory中获取 代表@Service注解的ServiceBean的BeanDefinition;
- 获取ServiceBean的ref属性;
- 获取ServiceBean的名称;
- 注册别名,如果别名和ServiceBean的别名一样,就不需要注册别名, 不一样就以ServiceBean的Bean名称为键, referenceBeanName为值,放入别名缓冲中;
- 不存在的话,就往容器中注入生成的referenceBean;
privatevoidregisterReferenceBean(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
AbstractBeanDefinition beanDefinition =(AbstractBeanDefinition) beanFactory.getBeanDefinition(referencedBeanName);
RuntimeBeanReference runtimeBeanReference =(RuntimeBeanReference) beanDefinition.getPropertyValues().get("ref");// ServiceBean --- ref
String serviceBeanName = runtimeBeanReference.getBeanName();
beanFactory.registerAlias(serviceBeanName, beanName);}else{// Remote @Service Beanif(!beanFactory.containsBean(beanName)){
beanFactory.registerSingleton(beanName, referenceBean);}}}
cacheInjectedReferenceBean(referenceBean, injectedElement)
目的: 将生成的referenceBean实例,放入缓存;
- 如果是属性注入, 则放入injectedFieldReferenceBeanCache中;
- 如果是方法注入, 则放入injectedMethodReferenceBeanCache中;
privatevoidcacheInjectedReferenceBean(ReferenceBean referenceBean,
InjectionMetadata.InjectedElement injectedElement){if(injectedElement.getMember()instanceofField){
injectedFieldReferenceBeanCache.put(injectedElement, referenceBean);}elseif(injectedElement.getMember()instanceofMethod){
injectedMethodReferenceBeanCache.put(injectedElement, referenceBean);}}
getOrCreateProxy(referencedBeanName, referenceBeanName, referenceBean, injectedType)
目的: 创建一个代理对象返回;
为什么是代理对象,而不是上面容器中的服务实现类;
个人看法:
不同服务,分布在不同的机器上,如果是本地服务还好, 如果是远程服务, 在调用服务还需要额外操作,
例如负载均衡, 注册中心等功能;因此,不能直接返回服务实现类,而是返回代理对象, 公共的操作让代理对象去执行;
工作:
- 判断ServiceBean是否存在,存在则是本地服务, 不存在则是远程服务;
- 本地服务:会生成一个代理对象,代理对象的InvocationHandler会放入缓存中, 返回代理对象;
- 远程服务:调用get()获取一个代理对象返回;
private Object getOrCreateProxy(String referencedBeanName, String referenceBeanName, ReferenceBean referenceBean, Class<?> serviceInterfaceType){if(existsServiceBean(referencedBeanName)){// If the local @Service Bean exists, build a proxy of ReferenceBeanreturnnewProxyInstance(getClassLoader(),newClass[]{serviceInterfaceType},wrapInvocationHandler(referenceBeanName, referenceBean));}else{// ReferenceBean should be initialized and get immediately// 重点return referenceBean.get();}}private InvocationHandler wrapInvocationHandler(String referenceBeanName, ReferenceBean referenceBean){return localReferenceBeanInvocationHandlerCache.computeIfAbsent(referenceBeanName, name ->newReferenceBeanInvocationHandler(referenceBean));}
总结
@Reference注解服务引入的过程:
有了这些逻辑,@Reference注解服务引入的过程是这样的:
- 得到当前所引入服务对应的ServiceBean的beanName(源码中叫referencedBeanName)
- 根据@Reference注解的所有信息+属性接口类型得到一个referenceBeanName
- 根据referenceBeanName从referenceBeanCache获取对应的ReferenceBean,如果没有则创建一个ReferenceBean
- 根据referencedBeanName(ServiceBean的beanName)判断Spring容器中是否存在该bean,如果存在则给ref属性所对应的bean取一个别名,别名为referenceBeanName。 a. 如果Spring容器中不存在referencedBeanName对应的bean,则判断容器中是否存在referenceBeanName所对应的Bean,如果不存在则将创建出来的ReferenceBean注册到Spring容器中(此处这么做就支持了可以通过@Autowired注解也可以使用服务了,ReferenceBean是一个FactoryBean)
- 如果referencedBeanName存在对应的Bean,则额外生成一个代理对象,代理对象的InvocationHandler会缓存在localReferenceBeanInvocationHandlerCache中,这样如果引入的是同一个服务,并且这个服务在本地,
- 如果referencedBeanName不存在对应的Bean,则直接调用ReferenceBean的get()方法得到一个代理对象
版权归原作者 ~玄霄- 所有, 如有侵权,请联系我们删除。