spring source code-third post processor

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

In the spring source code, in this method, the second to eighth post-processor calls are completed. In the previous notes of the inferred constructor , the call to the second post-processor is recorded. This note , Mainly records the use of the third post processor

Source code

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;
	}
}

This is where the third post-processor is called. Among different post-processors, the third post-processor has completed different operations, but there is a commonality, which is to find out some annotations to be processed in advance , I’m not sure if I’m correct in this sentence, I will introduce them one by one below

Spring comes with some post processors, let’s take a rough look at each post processor and the operations done in the third post processor

AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

First of all, the following operations are completed in the postProcessMergedBeanDefinition of this post processor: find out the bean that is currently being initialized, add @Autowired or @Value annotated methods and properties, and store them in the map collection, the key is beanName, value is the attributes found

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

In this method, the called findAutowiringMetadata() method will also be called when the sixth post processor is called, but in the findAutowiringMetadata() method, a map set is used to store the attributes to be injected And method, so when the post processor filled with the sixth attribute is called, it will not be parsed again, but directly obtained from the cache. The first parsing is here, the third post-processing Parsed when the device is executed

/**
 * 这里使用的模式是单例设计模式中的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);
}

I won’t explain too much here, the comments are fairly clear

CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

The operation done in this post processor is similar to the previous one, except that the method of this post processor is to process the @Resource annotation, that is, to find the field and method with the @Resource annotation, and then store it in the map In the collection, the thoughts are the same, but in the judgment conditions, the annotations are different.

InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

The third post processor of this post processor is to find the initialization method annotation and the destruction annotation, that is, the @PostConstruct and @PreDestroy annotations

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);
}

Here destroyAnnotationType and initAnnotationType are respectively assigned when the CommonAnnotationBeanPostProcessor is initialized, because CommonAnnotationBeanPostProcessor is a subclass of InitDestroyAnnotationBeanPostProcessor

Insert picture description here

I don’t look at the others. In Spring’s own post processor, the operations performed by the postProcessMergedBeanDefinition() method are basically similar. We can understand that they all mention doing some preprocessing, because @Autowired and @Value, @Resource these annotations are useful in the sixth post processor, that is, when attribute injection; the initialization annotation is used when the seventh post processor is called, and the parsed @PostConstruct is added. Annotation method, and then directly obtained from the map collection, no need to parse again

Guess you like

Origin blog.csdn.net/CPLASF_/article/details/111472800