前言
Spring bean生命周期中,注入点的搜索发生在bean实例化完成之后。这是BeanDefinition的一个后置处理器扩展点。
MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition(beanDefinition, mbeanType, beanName)
这里,寻找@Autowired、@Value、@Inject注解的注入点的实现类是:AutowiredAnnotationBeanPostProcessor。
而寻找@Resource注解的注入点的实现类是:CommonAnnotationBeanPostProcessor。
本文将重点讲述@Autowired是如何被找到的。
注入点结构
搜索注入点时,显然需要遍历所有的字段和方法,并将找到的注入点保存到InjectedElement类中。AutowiredAnnotationBeanPostProcessor重新实现了这个类。
- member:它是Field、Method的父类。
- pd:属性描述符。
- cached:标识是否已经被搜索过。
- cachedFieldValue:这是AutowiredFieldElement类的属性,如果之前已经被搜索过,它会把找到的bean名称和类型封装到ShortcutDependencyDescriptor中,这样下次再来时,直接使用名称进行搜索。
- cachedMethodArguments:这是AutowiredMethodElement类的属性,与上述类似,只不过是将参数按顺序存储在数组中。
注入点的搜索是Spring的一个扩展点,找到的注入点会被保存在集合中。
public class InjectionMetadata {
private final Class<?> targetClass;
//保存注入点的集合
private final Collection<InjectedElement> injectedElements;
}
对于原型bean,每次注入时都重新搜索注入点会很低效,所以InjectionMetadata会被缓存起来。
public class AutowiredAnnotationBeanPostProcessor{
private final Map<Class<?>, Constructor<?>[]> candidateConstructorsCache = new ConcurrentHashMap<>(256);
}
AutowiredAnnotationBeanPostProcessor.candidateConstructorsCache
下次再次需要时,会通过bean名称或Class名称在缓存中进行查找,从而避免再次搜索注入点。
搜索注入点
首先,遍历类中所有的Field属性,检查是否有@Autowired、@Value、@Inject注解之一,如果有,并且属性不是静态的,那么它就是一个注入点。
然后,遍历类中所有的Method方法,检查方法上是否存在@Autowired、@Value、@Inject中的任一注解,并且方法不是静态的。
这个过程会持续到遍历父类,直到没有父类为止。
最后,将所有找到的注入点保存到集合中。
本文暂时没有评论,来添加一个吧(●'◡'●)