Spring源码-applyMergedBeanDefinitionPostProcessors方法处理@PreDestroy、@PostConstruct @Resource

调用起始位置

AbstractAutowireCapableBeanFactory#doCreateBean方法调用当前类下applyMergedBeanDefinitionPostProcessors方法
在这里插入图片描述
在这里插入图片描述

CommonAnnotationBeanPostProcessor类

在这里插入图片描述

添加PostConstruct和PreDestroy
在这里插入图片描述
实际是InitDestroyAnnotationBeanPostProcessor的方法


	/**
	 * Specify the init annotation to check for, indicating initialization
	 * methods to call after configuration of a bean.
	 * <p>Any custom annotation can be used, since there are no required
	 * annotation attributes. There is no default, although a typical choice
	 * is the JSR-250 {@link javax.annotation.PostConstruct} annotation.
	 */
	public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {
		this.initAnnotationType = initAnnotationType;
	}

	/**
	 * Specify the destroy annotation to check for, indicating destruction
	 * methods to call when the context is shutting down.
	 * <p>Any custom annotation can be used, since there are no required
	 * annotation attributes. There is no default, although a typical choice
	 * is the JSR-250 {@link javax.annotation.PreDestroy} annotation.
	 */
	public void setDestroyAnnotationType(Class<? extends Annotation> destroyAnnotationType) {
		this.destroyAnnotationType = destroyAnnotationType;
	}

添加Resource
在这里插入图片描述
static方法赋值的属性字段在common类里

	private static final Set<Class<? extends Annotation>> resourceAnnotationTypes = new LinkedHashSet<>(4);

调用CommonAnnotationBeanPostProcessor的postProcessMergedBeanDefinition

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

/**
	 * 构造生命周期元数据(解析带@PostConstruct和@PreDestroy注解的方法),当其构造完成后会将元数据缓存到lifecycleMetadataCache集合中并返回
	 * 此时就完成了相关方法(初始化方法和销毁方法)的扫描解析和缓存工作
	 *
	 * @param clazz
	 * @return
	 */
	private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
		if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
			return this.emptyLifecycleMetadata;
		}

		// 实例化后的回调方法(@PostConstruct)
		List<LifecycleElement> initMethods = new ArrayList<>();
		// 销毁前的回调方法(@PreDestroy)
		List<LifecycleElement> destroyMethods = new ArrayList<>();
		// 获取正在处理的目标类
		Class<?> targetClass = clazz;

		do {
			// 保存每一轮循环搜索到的相关方法
			final List<LifecycleElement> currInitMethods = new ArrayList<>();
			final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
			// 反射获取当前类中的所有方法并依次对其调用第二个参数的lambda表达式
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				// 当前方法的注解中包含initAnnotationType注解时(@PostConstruct)
				if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
					// 如果有,把它封装成LifecycleElement对象,存储起来
					LifecycleElement element = new LifecycleElement(method);
					// 将创建好的元素添加到集合中
					currInitMethods.add(element);
					if (logger.isTraceEnabled()) {
						logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
					}
				}
				// 当前方法的注解中包含destroyAnnotationType注解(PreDestroy)
				if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
					// 如果有,把它封装成LifecycleElement对象,存储起来
					currDestroyMethods.add(new LifecycleElement(method));
					if (logger.isTraceEnabled()) {
						logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
					}
				}
			});

			// 将本次循环中获取到的对应方法集合保存到总集合中
			initMethods.addAll(0, currInitMethods);
			// 销毁方法父类晚于子类
			destroyMethods.addAll(currDestroyMethods);
			// 获取当前类的父类
			targetClass = targetClass.getSuperclass();
		}
		// 如果当前类存在父类且父类不为object基类则循环对父类进行处理
		while (targetClass != null && targetClass != Object.class);

		// 有一个不为空就封装一个LifecycleMetadata对象,否则就返回空的emptyLifecycleMetadata
		return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
				new LifecycleMetadata(clazz, initMethods, destroyMethods));
	}
@PostConstruct
public void test() {
    System.out.println("PostConstruct");
}

如果在bean中,方法上有@PostConstruct注解:

该方法将会在InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization中进行调用

在这里插入图片描述
这里执行:

		public void invokeInitMethods(Object target, String beanName) throws Throwable {
			Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
			Collection<LifecycleElement> initMethodsToIterate =
					(checkedInitMethods != null ? checkedInitMethods : this.initMethods);
			if (!initMethodsToIterate.isEmpty()) {
				for (LifecycleElement element : initMethodsToIterate) {
					if (logger.isTraceEnabled()) {
						logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());
					}
					element.invoke(target);
				}
			}
		}

AutowiredAnnotationBeanPostProcessor

	// 该处理器支持解析的注解们,默认支持的是3个
	private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4);

	/**
	 * 构造方法,完成对应注解的注入
	 *
	 * Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
	 * standard {@link Autowired @Autowired} and {@link Value @Value} annotations.
	 * <p>Also supports JSR-330's {@link javax.inject.Inject @Inject} annotation,
	 * if available.
	 */
	@SuppressWarnings("unchecked")
	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.
		}
	}


	/**
	 * 处理合并的bean定义信息
	 * 1、解析@Autowired等注解然后转换
	 * 2、把注解信息转换为InjectionMetadata然后缓存到上面的injectionMetadataCache里面
	 * @param beanDefinition the merged bean definition for the bean
	 * @param beanType the actual type of the managed bean instance
	 * @param beanName the name of the bean
	 */
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		// 解析注解并缓存
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}
	/**
	 *  方法名为查找到该bean的依赖注入元信息,内部只要查找到了就会加入到缓存内,下次没必要再重复查找了~
	 * 	它是一个模版方法,真正做事的方法是:buildAutowiringMetadata,它复杂把标注有@Autowired注解的属性转换为Metadata元数据信息,从而消除注解的定义
	 * 	此处查找包括了字段依赖注入和方法依赖注入~~~
	 * @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.
		String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
		// Quick check on the concurrent map first, with minimal locking.
		// 从缓存中获取该类的信息
		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);
					}
					// 构建自动装配的属性和方法元数据 去寻找有Autowired和Value注解的属性和方法,也包括自定义的父类的,封装成AutowiredMethodElement放入集合中
					metadata = buildAutowiringMetadata(clazz);
					this.injectionMetadataCache.put(cacheKey, metadata);
				}
			}
		}
		return metadata;
	}
/**
	 * 去寻找有Autowired和Value注解的属性和方法,也包括自定义的父类的,封装成AutowiredMethodElement放入集合中
	 * @param clazz
	 * @return
	 */
	private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		// 如果clazz是JDK中的类,直接忽略,因为不可能标注有这些标注
		if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
			return InjectionMetadata.EMPTY;
		}

		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
		Class<?> targetClass = clazz;

		do {
			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

			// 遍历类中的每个属性,判断属性是否包含指定的属性(通过 findAutowiredAnnotation 方法)
			// 如果存在则保存,这里注意,属性保存的类型是 AutowiredFieldElement
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
				if (ann != null) {
					//Autowired注解不支持静态方法
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					//查看是否是required的
					boolean required = determineRequiredStatus(ann);
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});


			// 遍历类中的每个方法,判断属性是否包含指定的属性(通过 findAutowiredAnnotation 方法)
			// 如果存在则保存,这里注意,方法保存的类型是 AutowiredMethodElement
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
					return;
				}
				MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
					if (Modifier.isStatic(method.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					// 如果方法没有入参,输出日志,不做任何处理
					if (method.getParameterCount() == 0) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					boolean required = determineRequiredStatus(ann);
					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
					// AutowiredMethodElement里封装了一个PropertyDescriptor(比字段多了一个参数)
					currElements.add(new AutowiredMethodElement(method, required, pd));
				}
			});

			// 父类的都放在第一位,所以父类是最先完成依赖注入的
			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);

		// InjectionMetadata就是对clazz和elements的一个包装而已
		return InjectionMetadata.forElements(elements, clazz);
	}

	/**
	 * 只要方法/属性上但凡标注有一个注解,就立马返回了
	 * @param ao
	 * @return
	 */
	@Nullable
	private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
		MergedAnnotations annotations = MergedAnnotations.from(ao);
		for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
			MergedAnnotation<?> annotation = annotations.get(type);
			if (annotation.isPresent()) {
				return annotation;
			}
		}
		return null;
	}
  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
@PostConstruct注解和@PreDestroy注解是Java EE规范中定义的两个注解。@PostConstruct注解用于标注一个方法,该方法会在依赖注入完成后被自动调用,通常用于在初始化阶段执行一些操作。而@PreDestroy注解用于标注一个方法,该方法会在对象销毁之前被自动调用,通常用于在销毁前执行一些清理操作。 在引用中提到,我们可以在Dog类中使用@PostConstruct注解和@PreDestroy注解来分别标注init()方法destroy()方法。@PostConstruct注解修饰的方法会在依赖注入完成后被调用,类似于初始化方法。而@PreDestroy注解修饰的方法会在对象销毁之前被调用,类似于销毁方法。 在引用中提到,被@PreDestroy注解修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次。它会在destroy()方法之后执行,而destroy()方法是Servlet生命周期中的一个方法,用于在Servlet被彻底卸载之前执行一些清理操作。 综上所述,@PostConstruct注解和@PreDestroy注解是用于在依赖注入完成后执行初始化操作和在对象销毁前执行清理操作的注解。它们在Java EE开发中常用于管理对象的生命周期。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Spring注解驱动之@PostConstruct和PreDestroy注解](https://blog.csdn.net/tianzhonghaoqing/article/details/126689583)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值