博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring的Bean后置处理器之AutowiredAnnotationBeanPostProcessor
阅读量:4077 次
发布时间:2019-05-25

本文共 17994 字,大约阅读时间需要 59 分钟。

目录


关于Bean后置处理器的介绍见:


本文能帮你解答的问题

  1. @Autowired注解是如何完成属性自动注入的?
  2. 如何改变bean实例化构造函数的选择?
  3. @Autowired查找候选者过程是什么?
  4. @Qualifier与@Primary的作用?

类介绍

作用

  1. 选择标注了@Autowired的构造函数作为实例化用到的构造函数。
  2. 处理@Autowired和@Value注解的属性字段,注入属性值
  3. 处理@Autowired和@Value注解的方法,注入对应的值。
  4. 处理@Lookup注解的方法。

类结构

从类图可以看出:

  1. AutowiredAnnotationBeanPostProcessor主要继承了InstantiationAwareBeanPostProcessor、SmartInstantiationAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor。
  2. 主要实现了determineCandidateConstructors、postProcessMergedBeanDefinition、postProcessPropertyValues方法

继承父类说明

InstantiationAwareBeanPostProcessor

提供了bean实例化前后对bean的操作以及在属性赋值前,传递属性值的postProcessProperties方法。

SmartInstantiationAwareBeanPostProcessor

主要提供了实例化前自定义选择构造函数的方法。

MergedBeanDefinitionPostProcessor

用于处理合并后的BeanDefinition,在bean实例化后、属性赋值前回调。

BeanFactoryAware

回调提供BeanFactory对象,在属性赋值后、bean初始化前回调。

构造函数

public AutowiredAnnotationBeanPostProcessor() {		this.autowiredAnnotationTypes.add(Autowired.class);		this.autowiredAnnotationTypes.add(Value.class);		try {			this.autowiredAnnotationTypes.add((Class
) ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader())); logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring"); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. } }

通过构造函数可以大概猜测该后置处理器的作用。

实现方法分析

针对AutowiredAnnotationBeanPostProcessor主要实现了determineCandidateConstructors、postProcessMergedBeanDefinition、postProcessProperties,按照执行的先后顺序依次分析。

determineCandidateConstructors

调用时机:bean实例化前调用。

实现的逻辑主要分两部分,一部分是处理@Lookup注解,一部分是处理构造函数上的@Autowired注解。

处理@Lookup注解方法

@Lookup的作用是在方法上的注解,被其标注的方法会被重写,然后根据其返回值的类型,容器调用BeanFactory的getBean()方法来返回一个bean。

使用场景:当一个单例的bean依赖的bean是多例的时候,如果需要单例的bean每次获取依赖的bean都是不同实例,则可以通过@Lookup实现。

@Lookup的主要作用就是在这里实现的。

if (!this.lookupMethodsChecked.contains(beanName)) {			if (AnnotationUtils.isCandidateClass(beanClass, Lookup.class)) {				try {					Class
targetClass = beanClass; do { ReflectionUtils.doWithLocalMethods(targetClass, method -> { //查找方法上的Lookup注解 Lookup lookup = method.getAnnotation(Lookup.class); if (lookup != null) { Assert.state(this.beanFactory != null, "No BeanFactory available"); LookupOverride override = new LookupOverride(method, lookup.value()); try { RootBeanDefinition mbd = (RootBeanDefinition) this.beanFactory.getMergedBeanDefinition(beanName); mbd.getMethodOverrides().addOverride(override); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(beanName, "Cannot apply @Lookup to beans without corresponding bean definition"); } } }); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Lookup method resolution failed", ex); } } this.lookupMethodsChecked.add(beanName); }

选择@Autowired的构造函数

当@Autowired标注在某个构造函数的时候,则bean的实例化会使用当前构造函数,同时注入构造函数指定的依赖。

例如下面的例子:

@Componentpublic class Service2 {    private Service1 service1;    public Service2() {        System.out.println(this.getClass() + "无参构造器");    }    @Autowired    public Service2(Service1 service1) {        System.out.println(this.getClass() + "有参构造器");        this.service1 = service1;    }}

源码:

Constructor
[] candidateConstructors = this.candidateConstructorsCache.get(beanClass); if (candidateConstructors == null) { synchronized (this.candidateConstructorsCache) { candidateConstructors = this.candidateConstructorsCache.get(beanClass); if (candidateConstructors == null) { Constructor
[] rawCandidates; //获取声明的构造函数 rawCandidates = beanClass.getDeclaredConstructors(); List
> candidates = new ArrayList<>(rawCandidates.length); Constructor
requiredConstructor = null; Constructor
defaultConstructor = null; Constructor
primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass); int nonSyntheticConstructors = 0; for (Constructor
candidate : rawCandidates) { if (!candidate.isSynthetic()) { nonSyntheticConstructors++; } else if (primaryConstructor != null) { continue; } //查找@Autowired注解 MergedAnnotation
ann = findAutowiredAnnotation(candidate); //。。。 //如果存在 if (ann != null) { //required值是否是true boolean required = determineRequiredStatus(ann); if (required) { if (!candidates.isEmpty()) { throw new BeanCreationException(beanName, "Invalid autowire-marked constructors: " + candidates + ". Found constructor with 'required' Autowired annotation: " + candidate); } requiredConstructor = candidate; } candidates.add(candidate); } else if (candidate.getParameterCount() == 0) { defaultConstructor = candidate; } } if (!candidates.isEmpty()) { // Add default constructor to list of optional constructors, as fallback. if (requiredConstructor == null) { if (defaultConstructor != null) { candidates.add(defaultConstructor); } else if (candidates.size() == 1 && logger.isInfoEnabled()) { logger.info("Inconsistent constructor declaration on bean with name '" + beanName + "': single autowire-marked constructor flagged as optional - " + "this constructor is effectively required since there is no " + "default constructor to fall back to: " + candidates.get(0)); } } candidateConstructors = candidates.toArray(new Constructor
[0]); } else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) { candidateConstructors = new Constructor
[] {rawCandidates[0]}; } else if (nonSyntheticConstructors == 2 && primaryConstructor != null && defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) { candidateConstructors = new Constructor
[] {primaryConstructor, defaultConstructor}; } else if (nonSyntheticConstructors == 1 && primaryConstructor != null) { candidateConstructors = new Constructor
[] {primaryConstructor}; } else { candidateConstructors = new Constructor
[0]; } //将选中的构造函数缓存起来 this.candidateConstructorsCache.put(beanClass, candidateConstructors); } } } return (candidateConstructors.length > 0 ? candidateConstructors : null); }

postProcessMergedBeanDefinition

调用时机:在bean实例化后、属性赋值前回调。

作用:查找bean对应类中定义的@Autowired注解和@Value注解,并缓存起来

@Override	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class
beanType, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); }

findAutowiringMetadata方法内会调用buildAutowiringMetadata方法,将得到的InjectionMetadata放到injectionMetadataCache缓存起来,buildAutowiringMetadata主要分方法和字段上的@Autowired和@Value解析。

private InjectionMetadata buildAutowiringMetadata(final Class
clazz) { List
elements = new ArrayList<>(); Class
targetClass = clazz; do { final List
currElements = new ArrayList<>(); //处理字段上的Value和Autowired注解 ReflectionUtils.doWithLocalFields(targetClass, field -> { MergedAnnotation
ann = findAutowiredAnnotation(field); if (ann != null) { if (Modifier.isStatic(field.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static fields: " + field); } return; } boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field, required)); } }); /处理方法上的Autowired和Value注解 ReflectionUtils.doWithLocalMethods(targetClass, method -> { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } MergedAnnotation
ann = findAutowiredAnnotation(bridgedMethod); if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static methods: " + method); } return; } if (method.getParameterCount() == 0) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation should only be used on methods with parameters: " + method); } } boolean required = determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new AutowiredMethodElement(method, required, pd)); } }); elements.addAll(0, currElements); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return InjectionMetadata.forElements(elements, clazz); }

postProcessProperties

调用时机:属性赋值前回调。

从缓存中获取上一步缓存的InjectionMetadata调用inject方法注入属性值。

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {		    //从缓存中获取上一步缓存的InjectionMetadata		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);		try {		    //注入			metadata.inject(bean, beanName, pvs);		}		catch (BeanCreationException ex) {			throw ex;		}		catch (Throwable ex) {			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);		}		return pvs;	}

InjectionMetadata封装了标注了Autowired和Value注解的字段或者方法,通过InjectedElement表示。

分别由AutowiredFieldElement和AutowiredMethodElement表示,都是AutowiredAnnotationBeanPostProcessor内部类

//代表标注了注解的字段private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {    //注入逻辑所在的方法    protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {        //...    }}//代表标注了注解的方法private class AutowiredMethodElement extends InjectionMetadata.InjectedElement {    //注入逻辑所在的方法    protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {        //...    }}

这里分析下字段的注入逻辑。

  • 入口:AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject:
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {			Field field = (Field) this.member;			Object value;			if (this.cached) {				value = resolvedCachedArgument(beanName, this.cachedFieldValue);			}			else {			    //封装依赖字段				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);				desc.setContainingClass(bean.getClass());				Set
autowiredBeanNames = new LinkedHashSet<>(1); Assert.state(beanFactory != null, "No BeanFactory available"); TypeConverter typeConverter = beanFactory.getTypeConverter(); try { //获取依赖字段对应的value,这里面逻辑较深,主要涉及很多选择的先后顺序逻辑 value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } synchronized (this) { if (!this.cached) { if (value != null || this.required) { this.cachedFieldValue = desc; registerDependentBeans(beanName, autowiredBeanNames); if (autowiredBeanNames.size() == 1) { String autowiredBeanName = autowiredBeanNames.iterator().next(); if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { this.cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } else { this.cachedFieldValue = null; } this.cached = true; } } } if (value != null) { //反射调用字段的set方法,注入value到bean中 ReflectionUtils.makeAccessible(field); field.set(bean, value); } }

通过查找获取依赖字段对应的value,然后利用反射将value set到对应bean的属性字段中。

如何获取属性的值逻辑主要在DefaultListableBeanFactory#resolveDependency方法中,这里面涉及到@Autowired查找候选者的具体过程。

value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);

@Autowired查找候选者过程

查找的大致处理逻辑为:

按类型找->通过限定符@Qualifier过滤->@Primary->@Priority->根据名称找(字段名称或者方法名称)

主干源码

  • 代码入口
DefaultListableBeanFactory#resolveDependency    ->DefaultListableBeanFactory#doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,			@Nullable Set
autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); try { Object shortcut = descriptor.resolveShortcut(this); if (shortcut != null) { return shortcut; } Class
type = descriptor.getDependencyType(); //处理@Value注解 Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { //。。。 } //处理需要注入多个bean的属性值类型,例如List、Map、Stream Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); if (multipleBeans != null) { return multipleBeans; } //根据type获取需要注入的bean,key为bean的名称。 Map
matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.isEmpty()) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } return null; } String autowiredBeanName; Object instanceCandidate; //如果匹配到的注入的bean存在多个 if (matchingBeans.size() > 1) { //选择一个满足条件的beaNname,这里主要处理@Primary和@Priority注解 autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (autowiredBeanName == null) { if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans); } else { // In case of an optional Collection/Map, silently ignore a non-unique case: // possibly it was meant to be an empty collection of multiple regular beans // (before 4.3 in particular when we didn't even look for collection beans). return null; } } //根据选中的beanName获取bean instanceCandidate = matchingBeans.get(autowiredBeanName); } else { // We have exactly one match. Map.Entry
entry = matchingBeans.entrySet().iterator().next(); autowiredBeanName = entry.getKey(); instanceCandidate = entry.getValue(); } if (autowiredBeanNames != null) { autowiredBeanNames.add(autowiredBeanName); } if (instanceCandidate instanceof Class) { instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); } Object result = instanceCandidate; if (result instanceof NullBean) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } result = null; } if (!ClassUtils.isAssignableValue(type, result)) { throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass()); } return result; } finally { ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); } }

查找过程

1. 获取属性的bean类型

从代表了依赖的DependencyDescriptor中获取依赖属性的class type。

Class
type = descriptor.getDependencyType();

2. 处理多bean的属性类型

判断依赖的bean类型是否属于多个bean的类型,例如Stream、数组、List、Map此类。如果是则直接处理成对应的类型并返回,查找候选者直接结束。

Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);	if (multipleBeans != null) {		return multipleBeans;	}

3. 根据类型查找所有的bean

根据依赖属性的type查找bean工厂中所有的bean,得到一个map,key为bean的名称、value为bean。

Map
matchingBeans = findAutowireCandidates(beanName, type, descriptor);

此步代码较深,当注入的bean上标注了@Qualifier,会根据指定的bean名称筛选出满足条件的bean,不满足条件的不会放到map返回。

根据@Qualifier筛选bean的逻辑在:QualifierAnnotationAutowireCandidateResolver#isAutowireCandidate中。

4. 根据规则从多个bean中筛选一个

判断上一步获取的所有bean是否超过1个,超过1个则需要继续查找,根据一定规则最终取到一个。

if (matchingBeans.size() > 1) {		autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);		if (autowiredBeanName == null) {			if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {				return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);			}			else {				return null;				}			}		instanceCandidate = matchingBeans.get(autowiredBeanName);	}

具体筛选出一个bean的逻辑在determineAutowireCandidate方法。

  1. 先根据@Primary注解筛选加了@Primary注解的bean名称
  2. 没有,则继续根据Priority注解筛选优先级最高的bean名称
  3. 依然没有,则尝试获取属性名称和bean名称一样的bean。
protected String determineAutowireCandidate(Map
candidates, DependencyDescriptor descriptor) { //先根据@Primary注解筛选加了@Primary注解的bean名称 Class
requiredType = descriptor.getDependencyType(); String primaryCandidate = determinePrimaryCandidate(candidates, requiredType); if (primaryCandidate != null) { return primaryCandidate; } //没有则继续根据Priority注解筛选优先级最高的bean名称 String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType); if (priorityCandidate != null) { return priorityCandidate; } // 依然没有?则根据属性名称来匹配bean for (Map.Entry
entry : candidates.entrySet()) { String candidateName = entry.getKey(); Object beanInstance = entry.getValue(); if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) || matchesBeanName(candidateName, descriptor.getDependencyName())) { return candidateName; } } return null; }

总结

  1. @Autowired属性注入是通过bean后置处理器AutowiredAnnotationBeanPostProcessor在bean生命周期不同阶段拦截完成。
  2. AutowiredAnnotationBeanPostProcessor通过实现SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors方法,在bean实例化前选择@Autowired注解的构造函数,同时注入属性,从而完成自定义构造函数的选择。
  3. 通过实现postProcessMergedBeanDefinition,在属性赋值前,缓存属性字段上的@Autowired和@Value注解信息。
  4. 通过实现postProcessProperties,在实例化后,属性赋值前,查找获取依赖字段对应的value,然后利用反射将value set到对应bean的属性字段中。
  5. @Autowired查找候选者过程为:按类型找->通过限定符@Qualifier过滤->@Primary->@Priority->根据名称找(字段名称或者方法名称)

转载地址:http://fbini.baihongyu.com/

你可能感兴趣的文章
我觉得还是把ACfly的传感器的逻辑弄清楚,这样再去二次开发好一些。(折腾半天发现有很关键一部分没有开源,怪不得找不到,这让我很失望)
查看>>
freertos工程似乎都是先创建一个任务,再在这个任务里面创建其他任务,似乎就像任务树
查看>>
无人机的高度自适应
查看>>
别人对ACfly的评价
查看>>
还有你怎么判断ACfly是正常接收到了数据,怎么从ACfly端能看到实时的T265传给ACfly的位置数据。
查看>>
我觉得对双目VIO+无人机,单单靠VIO这边输出很好的位置信息还是不够的,无人机这边还是需要做做滤波,比如防止跳变什么的,保证无人机的稳定。
查看>>
英特尔RealSense激光雷达摄像头L515拆解分析
查看>>
优象光流使用的一些注意事项(转载)(光流数据要融合其他传感器使用比较好)
查看>>
mavlink里面有个关键词 msg
查看>>
mavlink消息帧里最重要的两个东西,一个是msgid;一个是payload
查看>>
【无人机开发】通讯协议MavLink详解
查看>>
B站这个讲mavlink的视频不错(弄懂了很多东西)
查看>>
*我发觉不管是mavlink还是传感器驱动都是基于串口协议的一个更高层的协议!!!!!!!(没有协议没有规则是没有办法进行通信的)
查看>>
STM32控制APM飞控(四)MAVLINK协议深入理解之数据结构
查看>>
STM32控制APM飞控(五)MAVLINK的C源码的解释及MAVLINK心跳包
查看>>
STM32控制APM飞控(二)MAVLINK源码集成到stm32工程中
查看>>
STM32下mavlink的使用个人总结(包含对ACfly里面mavlink的分析,包含接收T265的位置信息的二次开发教程)
查看>>
MAVLink通讯协议在STM32上移植,并自定义协议(这篇还写了在STM32上怎么收发数据,调用哪些函数)
查看>>
结构体在STM32串口接收中的妙用
查看>>
mavlink协议发送与接收--串口版(这篇也讲了STM32上面用哪些函数收发)
查看>>