在Spring框架中,@PostConstruct注解、init-method属性、以及afterPropertiesSet()方法通常用于初始化Bean的逻辑。它们都提供了在Bean创建和初始化完成后执行的方法,但执行顺序有所不同。
想要知道@PostConstruct、init-method、afterPropertiesSet()的执行顺序,只要搞明白它们各安闲什么时候被谁调用就行了。
代码如下:- import org.springframework.beans.factory.InitializingBean;
- import javax.annotation.PostConstruct;
- public class Foo implements InitializingBean {
- public void init(){
- System.out.println("执行了init生命周期的初始化回调");
- }
- @PostConstruct
- public void postConstruct(){
- System.out.println("执行了postConstruct生命周期的初始化回调");
- }
- @Override
- public void afterPropertiesSet() {
- System.out.println("执行了afterPropertiesSet生命周期的初始化回调");
- }
- }
复制代码- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- @Configuration
- public class InitConfiguration {
- @Bean(initMethod = "init")
- public Foo getInitMethodBean() {
- return new Foo();
- }
- }
复制代码 执行启动类,可以看到在控制台中输出:- 执行了postConstruct生命周期的初始化回调
- 执行了afterPropertiesSet生命周期的初始化回调
- 执行了init生命周期的初始化回调
复制代码 @PostConstruct是Java EE 5引入的一个注解,它用于标记一个方法,该方法会在依赖注入完成后自动执行。这意味着,一旦Spring容器完成了Bean的实例化和属性赋值,就会调用这个方法。通常,我们会在这个方法中做一些初始化工作,比如启动服务、初始化数据库连接等。
init-method属性是Spring Bean的一个属性,它允许我们指定一个初始化方法。这个方法会在Bean实例化并完成属性注入后自动执行。与@PostConstruct注解不同的是,init-method属性并不依赖于Spring容器,因此可以在没有Spring的情况中运行。
afterPropertiesSet是SpringFramework中的一个初始化方法,它属于 InitializingBean接口的一部分。当bean的全部属性被Spring容器设置之后,这个方法会被自动调用。它允许开发者在bean属性设置完成之后执行一些特定的操作,如数据库连接池的初始化等。这个方法是在执行其他初始化方法之前被调用的。
源码分析:
通过断点调试发现几个初始化方法都定位到AbstractAutowireCapableBeanFactory的initializeBean方法中- protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
- if (System.getSecurityManager() != null) {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- @Override
- public Object run() {
- invokeAwareMethods(beanName, bean);
- return null;
- }
- }, getAccessControlContext());
- }
- else {
- invokeAwareMethods(beanName, bean);
- }
- Object wrappedBean = bean;
- if (mbd == null || !mbd.isSynthetic()) {
- // 此处执行的是@PostConstruct注解的方法 InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization
- wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
- }
- try {
- // 执行的是afterPropertiesSet和init-method方法
- 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()) {
- wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
- }
- return wrappedBean;
- }
复制代码 执行afterPropertiesSet和init-method方法,在invokeInitMethods方法里面,如下:- protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
- throws Throwable {
- boolean isInitializingBean = (bean instanceof InitializingBean);
- if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
- if (logger.isDebugEnabled()) {
- logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
- }
- if (System.getSecurityManager() != null) {
- try {
- AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- @Override
- public Object run() throws Exception {
- ((InitializingBean) bean).afterPropertiesSet();
- return null;
- }
- }, getAccessControlContext());
- }
- catch (PrivilegedActionException pae) {
- throw pae.getException();
- }
- }
- else {
- // 执行afterPropertiesSet方法
- ((InitializingBean) bean).afterPropertiesSet();
- }
- }
- if (mbd != null) {
- String initMethodName = mbd.getInitMethodName();
- if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
- !mbd.isExternallyManagedInitMethod(initMethodName)) {
- // 执行自定义的init-method方法
- invokeCustomInitMethod(beanName, bean, mbd);
- }
- }
- }
复制代码
最终的结论是:@PostConstruct > afterPropertiesSet() > initMethod()的顺序
往期面试题:
Java面试题:SimpleDateFormat是线程安全的吗?使用时应该注意什么?
Java面试题:细数ThreadLocal大坑,内存泄漏本可避免
Java面试题:请谈谈对ThreadLocal的理解?
Java面试题:为什么HashMap不建议使用对象作为Key?
Java面试题:你知道Spring的IOC吗?那么,它为什么这么重要呢?
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |