前言
本篇来分析 Spring 是如何知道 Bean 中的哪些属性是需要被注入的!
该方法位于 AbstractAutowireCapableBeanFactory
类。相信各位看到这段代码应该不会陌生了吧!执行 BeanPostProcessors
。
protected void applyMergedBeanDefinitionPostProcessors(
RootBeanDefinition mbd, Class <? > beanType, String beanName) {
for(BeanPostProcessor bp: getBeanPostProcessors()) {
if(bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (
MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
复制代码
这里会执行所有实现了MergedBeanDefinitionPostProcessor
接口的 BeanPostProcessor
。
可以看到实现了 MergedBeanDefinitionPostProcessor
接口的类还是挺多的。分别有以下实现:
- AutowiredAnnotationBeanPostProcessor:解析
Autowired
、Value
、Inject
注解。 - ScheduledAnnotationBeanPostProcessor:解析
Scheduled
注解。 - InitDestroyAnnotationBeanPostProcessor:解析
PreDestroy
、PostConstruct
注解。 - JmsListenerAnnotationBeanPostProcessor:解析
JmsListener
注解。 - PersistenceAnnotationBeanPostProcessor:解析
@PersistenceUnit
和@PersistenceContext
注解。 - CommonAnnotationBeanPostProcessor:解析
@Resource
、@WebServiceRef
、@EJB
注解。并且该类继承了InitDestroyAnnotationBeanPostProcessor
。
本篇将介绍 AutowiredAnnotationBeanPostProcessor
和CommonAnnotationBeanPostProcessor
这两个BeanPostProcessor
。
AutowiredAnnotationBeanPostProcessor
在所有的实现类中,选择AutowiredAnnotationBeanPostProcessor
类。先来看看AutowiredAnnotationBeanPostProcessor
类的继承图。
既然要解析这Autowired
、Value
、Inject
三个注解,那么在AutowiredAnnotationBeanPostProcessor
类中肯定要有这三个注解的相关代码。
public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class <? extends Annotation > ) 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.
}
}
复制代码
可以看到这是一个无参构造方法,往 autowiredAnnotationTypes
属性中添加值。后面逻辑肯定会用到这个属性,判断当前类中是否包含 autowiredAnnotationTypes
属性的值。
好的,下面进入到正题,看看是如何去寻找注入点的。
方法传入三个入参,分别如下:
- beanDefinition:当前 bean 的定义
- beanType:实例对象的类型
- beanName:bean 名称
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,
Class <? > beanType, String beanName) {
// 获取beanType中的注入点
InjectionMetadata metadata = findAutowiringMetadata(beanName,
beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
复制代码
重点看一下 findAutowiringMetadata
方法。
private InjectionMetadata findAutowiringMetadata(String beanName,
Class <? > clazz, @Nullable PropertyValues pvs) {
// 如果当前 beanName 为null,那就选择class对象的名称
String cacheKey = (StringUtils.hasLength(beanName) ? beanName :
clazz.getName());
// 从缓存中获取
InjectionMetadata metadata = this.injectionMetadataCache.get(
cacheKey);
//如果缓存中有,不需要再次解析
//needsRefresh = true 需要解析
if(InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized(this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if(InjectionMetadata.needsRefresh(metadata, clazz)) {
if(metadata != null) {
metadata.clear(pvs);
}
// 寻找当前clazz中的注入点,把所有注入点整合成为一个InjectionMetadata对象
metadata = buildAutowiringMetadata(clazz);
// 添加到缓存中
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
复制代码
调试进入 buildAutowiringMetadata
方法:
private InjectionMetadata buildAutowiringMetadata(final Class <? >
clazz) {
// 判断是不是候选者类,
//1、先判断注解的全限名称是否以"java."开头,如果是则返回true,否则进行第二步(如果类名的全路径是 java.xx.xx,启动的时候就会报错的)
//2、判断类的名称是否以"java."开头 或者 clazz的类型为 org.springframework.core.Ordered.class,如果是返回 false
if(!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
return InjectionMetadata.EMPTY;
}
List <InjectionMetadata.InjectedElement> elements = new ArrayList<> ();
Class <?> targetClass = clazz;
do {
final L