spring的@PostConstruct实现原理

概述

本文主要讲解bean生命周期中初始化相关后置处理器

生命周期回调方法

生命周期回调方法的实现对应着spring中InitDestroyAnnotationBeanPostProcessor这个后置处理器
在bean的生命周期中,当bean进入到初始化前这一阶段的时候,就调用其postProcessBeforeInitialization方法

	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
		try {
			// @PostConstruct
			metadata.invokeInitMethods(bean, beanName);
		}
		catch (InvocationTargetException ex) {......}
		return bean;
	}

LifecycleMetadata ,从这个名字就能知道,里面存储着申明周期回调方法的相关信息,的确,spring就是通过反射的方式,获取到当前bean里面标注了生命周期回调方法注解的方法,然后封装到这个对象里面
接下来看看spring具体如何去找这些注解的

private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
		if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
			return this.emptyLifecycleMetadata;
		}
		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 (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
					currDestroyMethods.add(new LifecycleElement(method));
				...}
			});
			initMethods.addAll(0, currInitMethods);
			destroyMethods.addAll(currDestroyMethods);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);
		return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
				new LifecycleMetadata(clazz, initMethods, destroyMethods));
	}

其核心的方法时ReflectionUtils.doWithLocalMethods,这是spring内部的反射工具类,在doWithLocalMethods,通过反射获取到所有的Method对象,然后回调 作为参数的表达式,就会去判断 method.isAnnotationPresent(this.initAnnotationType)
而initAnnotationType是什么呢??

	/*....
	....
 	* is the JSR-250 {@link javax.annotation.PostConstruct} annotation.
	 */
	public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {
		this.initAnnotationType = initAnnotationType;
	}

通过spring 的注解就可以很轻易的发现,initAnnotationType就是@PostConstruct这个注解
再回到buildLifecycleMetadata这个方法里面,如果说找到了标有@PostConstruct这个注解的方法就会将其包装为LifecycleElement
然后放入 currInitMethods
如果说找到了标有@PreDestroy的方法也会将其包装为LifecycleElement ,添加到currDestroyMethods这个集合中

完成上述的操作,实例对象有了,要执行的方法也有了,那么就可以通过反射进行回调执行了

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

总结

@PostConstruct的实现就是InitDestroyAnnotationBeanPostProcessor中postProcessBeforeInitialization这个方法的实现,
而这一步骤正是对应着bean的生命周期中的初始化前,具体实现就是先通过反射将所有的方法进行循环遍历,找到标注了@PostConstruct
和@PreDestroy的方法然后将其放入集合,最后再循环获取到集合里的方法,然后通过反射进行回调

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值