Spring整合Dubbo中@Reference注解解析原理
@Reference: 可以用在属性或者方法, 意味着需要引用某个Dubbo服务, 那么Dubbo整合Spring后, 我很好奇怎么把这个过程完成的。
package org.apache.dubbo.demo.provider;
public class Application {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
context.start();
System.in.read();
}
@Configuration
@EnableDubbo(scanBasePackages = "org.apache.dubbo.demo.provider")
@PropertySource("classpath:/spring/dubbo-provider.properties")
static class ProviderConfiguration {
}
}
//@EnabeDubbo注解
@EnableDubboConfig
@DubboComponentScan
public @interface EnableDubbo {
//该属性的值也是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")
boolean multipleConfig() default true;
}
- @DubboComponentScan: 用来扫描@Service 和@Reference注解修饰的类;
DubboComponentScanRegistrar
public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(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}
*/
private void registerReferenceAnnotationBeanPostProcessor(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属性;
- 注入容器中;
public class BeanRegistrar {
/**
* Register Infrastructure Bean
*
* @param beanDefinitionRegistry {@link BeanDefinitionRegistry}
* @param beanType the type of bean
* @param beanName the name of bean
*/
public static void registerInfrastructureBean(BeanDefinitionRegistry beanDefinitionRegistry,
String beanName,
Class<?> beanType) {
if (!beanDefinitionRegistry.containsBeanDefinition(beanName)) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanType);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
}
}
}
ReferenceAnnotationBeanPostProcessor
- 继承了AnnotationInjectedBeanPostProcessor类,该类又继承了MergedBeanDefinitionPostProcessor,InstantiationAwareBeanPostProcessorAdapter 类;
- 应用启动的时候, 对于我们引入服务的类, Spring会进行对这些类进行依赖注入(类似@Autowired)
- 依赖注入的时候会调用AnnotationInjectedBeanPostProcessor#postProcessPropertyValues()方法,这个方法里面使用了子类的处理逻辑,按照子类的处理逻辑进行依赖注入;
- 在依赖注入前,会先执行MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法, 子类AnnotationInjectedBeanPostProcessor实现了这个接口, 目的是扫描所有被@Reference注解修饰的方法和属性的准备工作;
public class ReferenceAnnotationBeanPostProcessor extends AnnotationInjectedBeanPostProcessor implements
ApplicationContextAware, ApplicationListener {
//...
}
public abstract class AnnotationInjectedBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered,
BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean {
//...
}
public abstract class InstantiationAwareBeanPostProcessorAdapter implements SmartInstantiationAwareBeanPostProcessor {
//....
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
}
MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法
由子类AnnotationInjectedBeanPostProcessor 实现了这个方法;
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
}
public abstract class AnnotationInjectedBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered,
BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean {
//...
@Override
public void postProcessMergedBeanDefinition(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,接下来就会使用这个类去进行属性注入
return new AnnotationInjectedBeanPostProcessor.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 = new LinkedList<AnnotationInjectedBeanPostProcessor.AnnotatedFieldElement>();
ReflectionUtils.doWithFields(beanClass, field -> {
for (Class<? extends Annotation> annotationType : getAnnotationTypes()) {
AnnotationAttributes attributes = getMergedAttributes(field, annotationType, getEnvironment(), true);
if (attributes != null) {
//...
elements.add(new AnnotatedFieldElement(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 = new LinkedList<AnnotationInjectedBeanPostProcessor.AnnotatedMethodElement>();
ReflectionUtils.doWithMethods(beanClass, method -> {
Method bridgedMethod = findBridgedMethod(method);
for (Class<? extends Annotation> 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(new AnnotatedMethodElement(method, pd, attributes));
}
}
});
return elements;
}
获取完之后, 退出, 返回AnnotatedInjectionMetadata到(一)步骤中的调用处,然后会将这些Field和Method信息放入缓存;
postProcessPropertyValues
InstantiationAwareBeanPostProcessorAdapter抽象类已经定义好了该方法,子类AnnotationInjectedBeanPostProcessor 重写该方法,进行@Reference的依赖注入过程;
public abstract class InstantiationAwareBeanPostProcessorAdapter implements SmartInstantiationAwareBeanPostProcessor {
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
}
}
public abstract class AnnotationInjectedBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered,
BeanFactoryAware, BeanClassLoaderAware, EnvironmentAware, DisposableBean {
@Override
public 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
- 执行属性注入;
public void inject(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方法
public class AnnotatedFieldElement extends InjectionMetadata.InjectedElement {}
inject工作:
- 获取Field的类型;
- 获取对象getInjectedObject
- 设置为可访问
- 反射给Field设值;
@Override
protected void inject(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 - 创建一个代理对象返回;也就是意味着,最后注入的属性是一个代理对象;
@Override
protected 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();
return getOrCreateProxy(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 = new StringBuilder("ServiceBean");
// Required
append(beanNameBuilder, interfaceClassName);
// Optional
append(beanNameBuilder, version);
append(beanNameBuilder, group);
// Build and remove last ":"
String rawBeanName = beanNameBuilder.toString();
// Resolve placeholders
return 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 = new StringBuilder("@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);
} else if (!referencedType.isAssignableFrom(referenceBean.getInterfaceClass())) {
//...
}
return referenceBean;
}
ReferenceBeanBuilder#build()
创建一个Reference对象;
工作:
- 创建一个ReferenceBean对象
- 给ReferenceBean对象的属性赋值
public final C build() throws Exception {
checkDependencies();
C configBean = doBuild();
configureBean(configBean);
//....
return configBean;
}
configureBean(C configBean)
作用: 设置ReferenceBean的属性;
工作:
- @Reference注解中的配置项赋值给configBean
- 配置注册中心;
- 配置监控中心;
- 配置Dubbo应用配置;
- 配置模块信息;
- 还是配置属性信息;
protected void configureBean(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;
@Override
protected void preConfigureBean(AnnotationAttributes attributes, ReferenceBean referenceBean) {
DataBinder dataBinder = new DataBinder(referenceBean);
// Register CustomEditors for special fields
// 去掉空格
dataBinder.registerCustomEditor(String.class, "filter", new StringTrimmerEditor(true));
dataBinder.registerCustomEditor(String.class, "listener", new StringTrimmerEditor(true));
// 你可以这么配@Reference(parameters = {"text=123"})
// 也可以这么配@Reference(parameters = {"text:123"})
// 最终都会转变为Map设置到referenceBean中的parameters
dataBinder.registerCustomEditor(Map.class, "parameters", new PropertyEditorSupport() {
@Override
public void setAsText(String text) throws java.lang.IllegalArgumentException {
// Trim all whitespace
String content = StringUtils.trimAllWhitespace(text);
if (!StringUtils.hasText(content)) { // No content , ignore directly
return;
}
// 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(new AnnotationPropertyValuesAdapter(attributes, applicationContext.getEnvironment(), IGNORE_FIELD_NAMES));
}
//工作流程:
//1. 设置上下文ApplicationContext;
//2. 设置接口;
//3. 设置ConsumerConfig配置; 对应的是 注解里面设置 的consumer 配置信息;
//4. 设置Methodconfig配置
//4. 调用afterPropertiesSet(), 还是设置属性星系;
@Override
protected void postConfigureBean(AnnotationAttributes attributes, ReferenceBean bean) throws Exception {
bean.setApplicationContext(applicationContext);
configureInterface(attributes, bean);
configureConsumerConfig(attributes, bean);
configureMethodConfig(attributes, bean);
bean.afterPropertiesSet();
}
public void afterPropertiesSet() 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) {
throw new IllegalStateException("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) {
throw new IllegalStateException("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) {
throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config);
}
moduleConfig = config;
}
}
if (moduleConfig != null) {
setModule(moduleConfig);
}
}
}
// 如果@Reference注解上没有配置registryIds
// 那么则看application或consumer上有没有配置registryIds
if (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 = new ArrayList<>();
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 elements
super.setMetadataReportConfig(metadataReportConfigMap.values().iterator().next());
} else if (metadataReportConfigMap != null && metadataReportConfigMap.size() > 1) {
throw new IllegalStateException("Multiple MetadataReport configs: " + metadataReportConfigMap);
}
}
// 如果@Reference注解中没有配置configCenter属性
// 那么则从Spring容器中找ConfigCenterConfig类型的bean
if (getConfigCenter() == null) {
Map<String, ConfigCenterConfig> configenterMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ConfigCenterConfig.class, false, false);
// 只能配一个ConfigCenterConfig
if (configenterMap != null && configenterMap.size() == 1) {
// 设置进去
super.setConfigCenter(configenterMap.values().iterator().next());
} else if (configenterMap != null && configenterMap.size() > 1) {
throw new IllegalStateException("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) {
throw new IllegalStateException("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) {
throw new IllegalStateException("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;
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
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 Bean
if (!beanFactory.containsBean(beanName)) {
beanFactory.registerSingleton(beanName, referenceBean);
}
}
}
cacheInjectedReferenceBean(referenceBean, injectedElement)
目的: 将生成的referenceBean实例,放入缓存;
- 如果是属性注入, 则放入injectedFieldReferenceBeanCache中;
- 如果是方法注入, 则放入injectedMethodReferenceBeanCache中;
private void cacheInjectedReferenceBean(ReferenceBean referenceBean,
InjectionMetadata.InjectedElement injectedElement) {
if (injectedElement.getMember() instanceof Field) {
injectedFieldReferenceBeanCache.put(injectedElement, referenceBean);
} else if (injectedElement.getMember() instanceof Method) {
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 ReferenceBean
return newProxyInstance(getClassLoader(), new Class[]{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 ->
new ReferenceBeanInvocationHandler(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()方法得到一个代理对象