深刻理解Spring IOC之擴展篇(三)、InitializingBean、@PostConstruct、SmartInitializingSingleton

本文主要介紹三個初始化的方式,分別是@PostConstruct,InitializingBean,以及SmartInitializingSingleton這三個,咱們直接三個一塊兒用,來看看代碼哈。app

@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");
    }
}
複製代碼

代碼很簡單,咱們來看看容器啓動後的結果:ide

咱們能夠看到,三種初始化方式對應的業務邏輯都被執行了,而且咱們能夠觀察到,@PostConstruct是最早被執行的,而後是InitializingBean,最後是SmartInitializingSingleton,那麼他們具體的區別是什麼呢?咱們一塊兒到源碼種看看。

調用初始化的代碼位於AbstractAutowireCapableBeanFactory中的initializeBean方法中post

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中最後幾行中發現:ui

而這個時候,全部的Bean都已經被初始化了。因此咱們在這裏作一個小小的總結:這三個初始化的方法,執行前後順序是@PostConstruct,而後是InitializingBean,最後是SmartInitializingSingleton。舉個使用上的小例子,若是A bean要依賴B bean初始化產生的數據的話,那麼就可讓A來實現SmartInitializingSingleton,B來實現InitializingBean或者使用@PostConstruct,InitializingBean和@PostConstruct這兩個初始化的方式在絕大多數狀況下都沒什麼差異。另外須要注意的是這三個初始化的方法,都不要和以前的BeanFactoryPostProcessor以及BeanPostProcessor一塊兒用,由於是在容器不一樣階段來作的事情,好比我舉一個例子:spa

@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 尚未被初始化,因此固然沒法執行嘍,這只不過是我隨隨便便就想到的一個,還有可能又其餘坑的,因此說盡量分開用。debug

寫文章不易,尤爲完了要對一個龐大的東西作總結更爲不易,因此你的贊對我很重要,求點個贊🥺~code

相關文章
相關標籤/搜索