@PostConstruct与afterPropertiesSet

在开发过程中,在某些情况,需要对一个bean做一些初始化的,但是在未采取构造注入的情况下,执行构造函数时,该对象的属性都还没有通过自动装配注入,因此,一般对于bean的初始化工作是无法放入到构造函数的。于是经常会使用@PostConstruct和继承InitializingBean的afterPropertiesSet做初始化,那么这两种方式有什么异同呢?

执行时机

     ...................
    populateBean(beanName, mbd, instanceWrapper);
    exposedObject = initializeBean(beanName, exposedObject, mbd);
     ..................

知道Bean创建过程的都知道populateBean之后,意味着该bean的属性已经注入完毕。
关键方法
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		//先执行invokeAwareMethods,通过XXAware接口注入bean需要的属性
      if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
    
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
            //执行BeanPostProcessor方法的前置方法
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
                    //执行Bean的初始化方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
            //执行BeanPostProcessor方法的后置方法
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

@PostConstract执行实际

通过断点发现@PostConstruct方法是通过CommonAnnotationBeanPostProcessor的前置方法执行的

@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
		try {
			metadata.invokeInitMethods(bean, beanName);
		}
		catch (InvocationTargetException ex) {
			throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
		}
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

afterPropertiesSet执行

通过上面关键方法initializeBean中的invokeInitMethods执行

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {
······················
		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
				((InitializingBean) bean).afterPropertiesSet();
		}

		if (mbd != null && bean.getClass() != NullBean.class) {
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}

通过省略的代码来看invokeInitMethods会执行InitializingBean的afterPropertiesSet方法,并且执行用户自定义在Beandifination中的初始化方法

总结

相同点:@PostConstruct和afterPropertiesSet都是在bean的属性注入完毕之后才执行,都可以用来进行bean 的初始化
区别:@PostConstruct是通过BeanPostProcessor的前置方法中执行的(我们也可以参考这个自定义注解实现),略早于通过继承InitializingBean的afterPropertiesSet初始化方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值