InitializingBean
記住一點:InitializingBean接口為bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是繼承該接口的子類,在初始化bean的時候會執行該方法。
下面看下簡單的例子:(環境是用Spring Boot搭建,直接用SpringtestApplication啟動即可)
<bean id="myInitializingBean" class="com.paic.phssp.springtest.init.MyInitializingBean" init-method="testInit"></bean>
package com.paic.phssp.springtest.init; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; /** * 繼承InitializingBean接口的類,在初始化bean的時候會執行該方法 */ //@Component public class MyInitializingBean implements InitializingBean { public MyInitializingBean() { System.out.println("MyInitializingBean...."); } @Override public void afterPropertiesSet() throws Exception { System.out.println("ceshi MyInitializingBean>>>>>>>>>>>>>>>>>>>"); } @PostConstruct //功能上近似init-method,但加載時機不同 public void test(){ System.out.println("PostConstruct >>>>>>>>>>>>"); } public void testInit(){ System.out.println("ceshi init-method"); } }
結果:
MyInitializingBean....
PostConstruct >>>>>>>>>>>>
ceshi MyInitializingBean>>>>>>>>>>>>>>>>>>>
ceshi init-method
說明:
通過上述輸出結果,三者的先后順序也就一目了然了:
Constructor > @PostConstruct > InitializingBean > init-method
(1)通過查看spring的加載bean的源碼類(AbstractAutowireCapableBeanFactory)可看出其中奧妙:
AbstractAutowireCapableBeanFactory.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"))) { if (this.logger.isTraceEnabled()) { this.logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged(() -> { ((InitializingBean)bean).afterPropertiesSet(); return null; }, this.getAccessControlContext()); } catch (PrivilegedActionException var6) { throw var6.getException(); } } else { ((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)) { this.invokeCustomInitMethod(beanName, bean, mbd); } } }
說明:

看下源碼:InitDestroyAnnotationBeanPostProcessor.class
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata metadata = this.findLifecycleMetadata(bean.getClass()); try {
//利用反射,執行注解方法 metadata.invokeInitMethods(bean, beanName); return bean; } catch (InvocationTargetException var5) { throw new BeanCreationException(beanName, "Invocation of init method failed", var5.getTargetException()); } catch (Throwable var6) { throw new BeanCreationException(beanName, "Failed to invoke init method", var6); } } private InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata findLifecycleMetadata(Class<?> clazz) { if (this.lifecycleMetadataCache == null) { return this.buildLifecycleMetadata(clazz); } else { InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata metadata = (InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata)this.lifecycleMetadataCache.get(clazz); if (metadata == null) { Map var3 = this.lifecycleMetadataCache; synchronized(this.lifecycleMetadataCache) { metadata = (InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata)this.lifecycleMetadataCache.get(clazz); if (metadata == null) { metadata = this.buildLifecycleMetadata(clazz); this.lifecycleMetadataCache.put(clazz, metadata); } return metadata; } } else { return metadata; } } } private InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata buildLifecycleMetadata(Class<?> clazz) { List<InitDestroyAnnotationBeanPostProcessor.LifecycleElement> initMethods = new ArrayList(); List<InitDestroyAnnotationBeanPostProcessor.LifecycleElement> destroyMethods = new ArrayList(); Class targetClass = clazz; do { List<InitDestroyAnnotationBeanPostProcessor.LifecycleElement> currInitMethods = new ArrayList(); List<InitDestroyAnnotationBeanPostProcessor.LifecycleElement> currDestroyMethods = new ArrayList(); ReflectionUtils.doWithLocalMethods(targetClass, (method) -> {
//判斷是否是指定的注解類型 if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) { InitDestroyAnnotationBeanPostProcessor.LifecycleElement element = new InitDestroyAnnotationBeanPostProcessor.LifecycleElement(method); currInitMethods.add(element); if (this.logger.isTraceEnabled()) { this.logger.trace("Found init method on class [" + clazz.getName() + "]: " + method); } } if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) { currDestroyMethods.add(new InitDestroyAnnotationBeanPostProcessor.LifecycleElement(method)); if (this.logger.isTraceEnabled()) { this.logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method); } } }); initMethods.addAll(0, currInitMethods); destroyMethods.addAll(currDestroyMethods); targetClass = targetClass.getSuperclass(); } while(targetClass != null && targetClass != Object.class); return new InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata(clazz, initMethods, destroyMethods); }
方法:buildLifecycleMetadata(),判斷是否是指定的注解類型,而這個屬性,在CommonAnnotationBeanPostProcessor.class構造方法中被初始化為PostConstruct。
public CommonAnnotationBeanPostProcessor() { this.setOrder(2147483644); this.setInitAnnotationType(PostConstruct.class); this.setDestroyAnnotationType(PreDestroy.class); this.ignoreResourceType("javax.xml.ws.WebServiceContext"); }
那么問題來了,以上只能說明實現了BeanPostProcessor的postProcessBeforeInitialization()方法,不足說明@PostConstruct 先InitializingBean 。
再看AbstractAutowireCapableBeanFactory.class 的initializeBean()方法。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(() -> { this.invokeAwareMethods(beanName, bean); return null; }, this.getAccessControlContext()); } else { this.invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName); } try { this.invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable var6) { throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
這下明顯了,下面小結下:
--> 調用BeanPostProcessor的postProcessBeforeInitialization方法 (@PostConstruct在此)
--> 調用bean實例的初始化方法(invokeInitMethods-> InitializingBean->init-method)
--> 調用BeanPostProcessor的postProcessAfterInitialization方法
參考: https://blog.csdn.net/zl834205311/article/details/78802584

其中AbstractApplicationContext.refresh()
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. // 為刷新工作做一些當前上下文 context 上的准備工作 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. // ApplicationContext 實現了 BeanFactory 接口,但是並非直接作為 Bean 容器。 // ApplicationContext 中真正直接作為 Bean 容器的是一個內部Bean工廠 BeanFactory, // 通過其方法 getBeanFactory() 得到,此方法在 AbstractApplicationContext 中 // 被聲明為 abstract, 其實現要求由實現子類提供。下面的語句 obtainFreshBeanFactory() // 內部就是通過調用 getBeanFactory() 獲得這個內部 Bean 工廠的。 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. // 准備當前上下文使用的Bean容器 BeanFactory,設置其標准上下文特征,比如類加載器等 // 1. BeanFactory 的類加載器設置為當前上下文的類加載器 // 2. BeanFactory 的Bean表達式解析器設置為 new StandardBeanExpressionResolver() // 3. BeanFactory 增加 BeanPostProcessror new ApplicationListenerDetector(this) // 4.三個單例Bean被注冊 : environment,systemProperties,systemEnvironment prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. // 在當前上下文使用的Bean容器BeanFactory的標准初始化完成后對其做一些修改。此時 // 所有的Bean definition都已經加載但是還沒有 Bean 被創建。 // 當前上下文使用的Bean容器 BeanFactory 的 post process // 1.當前上下文是 EmbeddedWebApplicationContext 時, // 這個步驟中會對 beanFactory 注冊一個 BeanPostProcessor : // WebApplicationContextServletContextAwareProcessor // 2.當前上下文是 AnnotationConfigEmbeddedWebApplicationContext 時, // 如果設置了 basePackages, // 這里會使用 AnnotatedBeanDefinitionReader掃描basePackages; // 如果設置了 annotatedClasses, // 這里會使用 ClassPathBeanDefinitionScanner登記annotatedClasses; postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. // 在 beanFactory 上調用 BeanFactoryPostProcessors, // 當前上下文可能會有多個 BeanFactoryPostProcessor 需要應用在 beanFactory 上 // **************************************************************** // 這里需要尤其注意區別 BeanFactoryPostProcessor 和 BeanPostProcessor // BeanFactoryPostProcessor : 作用在 Bean定義 上,用來定制修改 Bean定義 // BeanPostProcessor :作用在 Bean實例 上,用來修改或者包裝 Bean實例 // **************************************************************** // 該方法實際上將實現委托出去 : // PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors() invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. // 注冊 BeanPostProcessor // 該步驟實際工作委托給工具類 PostProcessorRegistrationDelegate 的靜態方法 // void registerBeanPostProcessors( // ConfigurableListableBeanFactory beanFactory, // AbstractApplicationContext applicationContext) registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. // 初始化當前上下文ApplicationContext要使用的 事件多播器 // ApplicationEventMulticaster applicationEventMulticaster。 // // 如果容器中已經注冊類型為ApplicationEventMulticaster並且名稱為 // applicationEventMulticaster 的Bean,則直接使用;否則, // 新建一個SimpleApplicationEventMulticaster實例並注冊到 // Bean容器,Bean名稱使用 applicationEventMulticaster。 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. // AbstractApplicationContext 中 onRefresh() 方法實現為空,其目的就是 // 留給實現子類一個機會做一些上下文相關的刷新工作。在一些特殊Bean初始化時,單 // 例 singleton Bean 初始化之前該方法被調用。 // 1. 當前上下文是 EmbeddedWebApplicationContext 時,該步驟會創建一個 // 內置的 Servlet 容器, 具體參考 EmbeddedWebApplicationContext 的 // 方法 void createEmbeddedServletContainer() onRefresh(); // Check for listener beans and register them. // 1. 將外部指定到當前上下文的 ApplicationListener 實例關聯到上下文多播器 // Q : 什么時候外部給當前上下文指定 ApplicationListener ? // A : 舉例說明,Springboot 應用 SpringApplication 的情況下,是在 // prepareContext()結尾時SpringApplicationRunListeners的 // contextLoaded() 調用中發生的,此時正在廣播事件 // ApplicationPreparedEvent // 2. 將實現了 ApplicationListener 接口的所有 Bean 關聯到上下文多播器 // 3. 如果上下文屬性earlyApplicationEvents中有要通知的事件,廣播出去 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. // 完成 BeanFactory 的初始化工作 // 1.BeanFactory凍結所有的Bean定義:不再可以修改或者做post process操作 // 2.確保所有的non-lazy-init單例Bean被初始化,也包括FactoryBean // 3.如果所初始化的單例Bean實現了接口SmartInitializingSingleton,調用 // 其方法 afterSingletonsInstantiated() finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. // 1. 初始化生命周期處理器 LifecycleProcessor, 使用已經存在的Bean或者 // 一個新的DefaultLifecycleProcessor實例; // 2. 生命周期處理器 LifecycleProcessor 上傳播 refresh 事件 // 3. 發布事件 ContextRefreshedEvent // 4. 如果存在 LiveBeansView MBean 的話,關聯到當前上下文 // 當前上下文是EmbeddedWebApplicationContext的情況下,還會: // 5. 啟動EmbeddedServletContainer,比如啟動內置 tomcat容器 // 6. 發布事件 EmbeddedServletContainerInitializedEvent finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }
org.springframework.context.support.AbstractApplicationContext#refresh的這一行代碼
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
protected final void refreshBeanFactory() throws BeansException { if (this.hasBeanFactory()) { this.destroyBeans(); this.closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = this.createBeanFactory(); beanFactory.setSerializationId(this.getId()); this.customizeBeanFactory(beanFactory); this.loadBeanDefinitions(beanFactory); Object var2 = this.beanFactoryMonitor; synchronized(this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException var5) { throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5); } }
進入到這個方法org.springframework.context.support.AbstractApplicationContext#destroyBeans
protected void destroyBeans() { this.getBeanFactory().destroySingletons(); }
org.springframework.beans.factory.support.DefaultListableBeanFactory#destroySingletons
@Override public void destroySingletons() { super.destroySingletons(); // 清除記錄的單例beanName的緩存 this.manualSingletonNames.clear(); clearByTypeCache(); }
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroySingletons

@Override public void destroySingletons() { super.destroySingletons(); // 清空beanFactory緩存 this.factoryBeanObjectCache.clear(); } public void destroySingletons() { if (logger.isDebugEnabled()) { logger.debug("Destroying singletons in " + this); } // 這里使用ConcurrentHashMap本地緩存單例的bean實例,訪問次數比較多,提搞並發量 synchronized (this.singletonObjects) { this.singletonsCurrentlyInDestruction = true; } String[] disposableBeanNames; // 這里是用LinkedHashMap本地緩存銷毀的bean實例 synchronized (this.disposableBeans) { disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet()); } for (int i = disposableBeanNames.length - 1; i >= 0; i--) { // 銷毀單例的bean destroySingleton(disposableBeanNames[i]); } this.containedBeanMap.clear(); this.dependentBeanMap.clear(); this.dependenciesForBeanMap.clear(); // 同步清空緩存 synchronized (this.singletonObjects) { this.singletonObjects.clear(); this.singletonFactories.clear(); this.earlySingletonObjects.clear(); this.registeredSingletons.clear(); this.singletonsCurrentlyInDestruction = false; } } public void destroySingleton(String beanName) { // Remove a registered singleton of the given name, if any.刪除單例的bean,從本地緩存中刪除 removeSingleton(beanName); // Destroy the corresponding DisposableBean instance. DisposableBean disposableBean; synchronized (this.disposableBeans) { // 從本地緩存中刪除 disposableBean = (DisposableBean) this.disposableBeans.remove(beanName); } // bean銷毀的邏輯 destroyBean(beanName, disposableBean); } protected void destroyBean(String beanName, @Nullable DisposableBean bean) { // Trigger destruction of dependent beans first... 先觸發依賴的bean銷毀,從本地緩存中刪除 Set<String> dependencies = this.dependentBeanMap.remove(beanName); if (dependencies != null) { if (logger.isDebugEnabled()) { logger.debug("Retrieved dependent beans for bean '" + beanName + "': " + dependencies); } for (String dependentBeanName : dependencies) { // 這里用了一個遞歸刪除單例bean,當這個bean沒有依賴的bean要刪除的時候,遞歸結束 destroySingleton(dependentBeanName); } } // Actually destroy the bean now... 這里開始刪除單例bean if (bean != null) { try { // bean可以實現DisposableBean這個接口,重寫父類的bean destory的方法 bean.destroy(); } catch (Throwable ex) { logger.error("Destroy method on bean with name '" + beanName + "' threw an exception", ex); } } // Trigger destruction of contained beans...從本地緩存中銷毀內部bean Set<String> containedBeans = this.containedBeanMap.remove(beanName); if (containedBeans != null) { for (String containedBeanName : containedBeans) { // 這個地方還是遞歸調用,刪除單例bean,當這個bean沒有內部bean時遞歸結束 destroySingleton(containedBeanName); } } // Remove destroyed bean from other beans' dependencies. 從其他bean依賴中刪除銷毀的bean synchronized (this.dependentBeanMap) { for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) { Map.Entry<String, Set<String>> entry = it.next(); Set<String> dependenciesToClean = entry.getValue(); dependenciesToClean.remove(beanName); if (dependenciesToClean.isEmpty()) { it.remove(); } } } // Remove destroyed bean's prepared dependency information.刪除銷毀的bean准備的依賴信息 this.dependenciesForBeanMap.remove(beanName); }
bean可以實現DisposableBean這個接口,重寫父類的bean destory的方法

@Override public void destroy() { // 執行beanPostProcessors,beanPostProcessors用對對bean的過程進行處理的抽象 if (!CollectionUtils.isEmpty(this.beanPostProcessors)) { for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) { // 在bean銷毀之前進行一些處理 processor.postProcessBeforeDestruction(this.bean, this.beanName); } } if (this.invokeDisposableBean) { if (logger.isDebugEnabled()) { logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'"); } try { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { ((DisposableBean) bean).destroy(); return null; }, acc); } else { // bean實現DisposableBean接口的方式,注解調用子類destroy方法 ((DisposableBean) bean).destroy(); } } catch (Throwable ex) { String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'"; if (logger.isDebugEnabled()) { logger.warn(msg, ex); } else { logger.warn(msg + ": " + ex); } } } if (this.destroyMethod != null) { // 執行bean定義中指定的bean銷毀方法 invokeCustomDestroyMethod(this.destroyMethod); } else if (this.destroyMethodName != null) { Method methodToCall = determineDestroyMethod(this.destroyMethodName); if (methodToCall != null) { invokeCustomDestroyMethod(methodToCall); } } }
具體結構如下: