本文主要介绍三个初始化的方式,分别是@PostConstruct,InitializingBean,以及SmartInitializingSingleton这三个,我们直接三个一起用,来看看代码哈。
@Component public class TestP implements InitializingBean, SmartInitializingSingleton { @PostConstruct public void test() { System.out.println("@PostConstruct"); } @Override public void afterPropertiesSet() throws Exception { // InitializingBean 的方法 System.out.println("afterPropertiesSet"); } @Override public void afterSingletonsInstantiated() { // SmartInitializingSingleton 的方法 System.out.println("afterSingletonsInstantiated"); } }
代码很简单,我们来看看容器启动后的结果:
我们可以看到,三种初始化方式对应的业务逻辑都被执行了,并且我们可以观察到,@PostConstruct是最先被执行的,然后是InitializingBean,最后是SmartInitializingSingleton,那么他们具体的区别是什么呢?我们一起到源码种看看。
调用初始化的代码位于AbstractAutowireCapableBeanFactory中的initializeBean方法中
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { // 调用几个Aware接口 if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { invokeAwareMethods(beanName, bean); return null; } }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } // 调用所有的BeanPostProcessor的postProcessBeforeInitialization Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // 调用InitializingBean的方法和自定义初始化方法 invokeInitMethods(beanName, wrappedBean, mbd); }catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } // 执行所有BeanPostProcessor的postProcessAfterInitialization方法 if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
在这个方法中,我们很明显的可以看到,InitializingBean的执行位置,那么@PostConstruct是在哪里执行的呢?经过debug,我们可以发现它是在调用所有的BeanPostProcessor的postProcessBeforeInitialization的时候被执行的(CommonAnnotationBeanPostProcessor中)。然后SmartInitializingSingleton这个东西需要先说一下,Spring4.0的时候是没有这个东西的,这个是4.1之后加入进来的,这个也可以用来做初始化之后的一些操作,那么它又是什么时候被执行的呢?我们可以在DefaultListableBeanFactory中的preInstantiateSingletons中最后几行中发现:
而这个时候,所有的Bean都已经被初始化了。所以我们在这里做一个小小的总结:这三个初始化的方法,执行先后顺序是@PostConstruct,然后是InitializingBean,最后是SmartInitializingSingleton。举个使用上的小例子,如果A bean要依赖B bean初始化产生的数据的话,那么就可以让A来实现SmartInitializingSingleton,B来实现InitializingBean或者使用@PostConstruct,InitializingBean和@PostConstruct这两个初始化的方式在绝大多数情况下都没什么差别。另外需要注意的是这三个初始化的方法,都不要和之前的BeanFactoryPostProcessor以及BeanPostProcessor一起用,因为是在容器不同阶段来做的事情,比如我举一个例子:
@Component public class AProcessor implements BeanPostProcessor, PriorityOrdered { @PostConstruct public void test() { System.out.println("AProcessor @PostConstruct"); } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("aa"); return null; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("bb"); return null; } @Override public int getOrder() { return 0; } }
这个类实现了BeanPostProcessor 和PriorityOrdered 这两个接口,然后我们启动之后发现@PostConstruct里面的东西并没有被执行,这个原因是因为这个类初始化的时候用作执行@PostConstruct的BeanPostProcessor 还没有被初始化,所以当然无法执行喽,这只不过是我随随便便就想到的一个,还有可能又其他坑的,所以说尽可能分开用。
写文章不易,尤其完了要对一个庞大的东西做总结更为不易,所以你的赞对我很重要,求点个赞🥺~