spring源码-第三个后置处理器

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集合中获取到,无需再次解析

猜你喜欢

转载自blog.csdn.net/CPLASF_/article/details/111472800