org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
在spring源码中,这个方法中,完成了第二个到第八个后置处理器的调用,前面的推断构造函数的笔记中,记录了对第二个后置处理器的调用,这篇笔记,主要记录第三个后置处理器的使用
源码
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
/**
* 第三次调用后置处理器 缓存注解信息;通过后置处理器处理合并之后的beanDefinition;在这里调用
* 后置处理器的时候,会把当前bean所需要注入的bean存放到checkedElements中,在属性注入的时候,会用到
*
* 这里说白了:就是提前对bean中的@Autowired、@Resource注解进行解析,获取到要注入的bean
*
* spring原生的后置处理器,在这里执行的有三个:
* AutowiredAnnotationBeanPostProcessor:处理@Autowired注解
* CommonAnnotationBeanPostProcessor:处理@Resource注解
* InitDestroyAnnotationBeanPostProcessor:处理初始化回调方法(@PostConstruct和@PreDestroy注解)
*/
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
这里就是第三个后置处理器调用的地方,在不同的后置处理器中,第三个后置处理器完成了不同的操作,但是有一个共性,都是提前找出要处理的一些注解,这句话我不确定我描述的是否正确,下面再一一介绍
spring自带了一些后置处理器,我们来大致的看下各个后置处理器,在第三个后置处理器中所完成的操作
AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
首先说明下,这个后置处理器的postProcessMergedBeanDefinition中完成了以下操作:找出当前正在初始化的bean中,添加了@Autowired或者@Value注解的方法和属性,存入到map集合中,key是beanName,value就是找到的这些属性
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
在这个方法中,所调用的findAutowiringMetadata()方法,在第六个后置处理器被调用的时候,也会被调用,但是在findAutowiringMetadata() 方法中,使用了一个map集合,存储要注入的属性和方法,所以,在第六个属性填充的后置处理器被调用的时候,就不会再次解析,而是直接从缓存中获取,第一次解析,就是在这里,第三个后置处理器执行的时候来解析的
/**
* 这里使用的模式是单例设计模式中的DCL模式
* 1.首先根据key,从map中判断是否需要进行解析
* 2.如果对应的value不为null,而且value对应的class就是当前要注入的clazz就无需解析
* 3.如果需要解析,就执行解析的逻辑
* 4.解析完成之后,将解析的结果和key存入到map集合中
*
* 所以:这个方法中,核心的逻辑是buildAutowiringMetadata(clazz);
* @param beanName
* @param clazz
* @param pvs
* @return
*/
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
// cachekey是beanName
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
//这里的map
InjectionMetadata 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);
}
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
/**
* 这个方法,可以分为三部分来看
* 1.最外层是一个do...while循环
* 2.内层会先遍历所有的属性,判断是否有@Autowired或者@Value属性
* 3.接着会遍历所有的method,判断是否有@Autowired或者@Value属性
*
* 最后会将所有添加了这两个注解的元素(field + method)包装成一个InjectionMetadata对象返回
* @param clazz
* @return
*/
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
Class<?> targetClass = clazz;
do {
//这里的list集合就是需要注入的元素元信息
final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
/**
* ReflectionUtils.doWithLocalFields是获取属性上添加了@Autowired或者@Value的属性信息
* ReflectionUtils.doWithLocalMethods 应该是获取方法上添加了这两个注解的信息
*/
ReflectionUtils.doWithLocalFields(targetClass, field -> {
//这个方法是找到当前bean的所有要注入属性对应的注解
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isWarnEnabled()) {
logger.warn("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);
// 根据当前class和class要注入的元素,build一个InjectionMetedata对象
return new InjectionMetadata(clazz, elements);
}
这里就不做过多解释了,注释中写的还算清晰
CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
这个后置处理器中完成的操作,和前面类似,只是这个后置处理器的该方法中,是来处理@Resource注解,也就是找到添加了@Resource注解的field和method,然后存入到map集合中,思想是一样的,只是判断条件中,注解不一样而已
InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
这个后置处理器的第三个后置处理器中,是查找初始化方法注解和销毁注解,也就是@PostConstruct和@PreDestroy注解
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
final boolean debug = logger.isDebugEnabled();
List<LifecycleElement> initMethods = new ArrayList<>();
List<LifecycleElement> destroyMethods = new ArrayList<>();
Class<?> targetClass = clazz;
do {
final List<LifecycleElement> currInitMethods = new ArrayList<>();
final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
LifecycleElement element = new LifecycleElement(method);
currInitMethods.add(element);
if (debug) {
logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
}
}
if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
currDestroyMethods.add(new LifecycleElement(method));
if (debug) {
logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);
}
}
});
initMethods.addAll(0, currInitMethods);
destroyMethods.addAll(currDestroyMethods);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
return new LifecycleMetadata(clazz, initMethods, destroyMethods);
}
这里的destroyAnnotationType和initAnnotationType分别是在初始化CommonAnnotationBeanPostProcessor这个后置处理器的时候,被赋值的,因为CommonAnnotationBeanPostProcessor是InitDestroyAnnotationBeanPostProcessor的子类
其他的就不看了,spring自己的后置处理器中,postProcessMergedBeanDefinition()这个方法所完成的操作,基本是类似的,我们可以理解为都是提起做一些预处理,因为@Autowired和@Value、@Resource这几个注解,在第六个后置处理器,也就是属性注入的时候,有用到;初始化注解在第七个后置处理器调用的时候,会使用到解析出来的加了@PostConstruct注解的方法,然后直接从map集合中获取到,无需再次解析