Spring是一個IOC容器框架,擁有DI依賴注入(Dependency Injection),DL依賴查找(Dependency Lookup)等功能。java
關於Spring Bean的生命週期,官方並無找到相關文檔。spring
下邊是我根據源碼分析出四個階段,作出的生命週期解讀:緩存
1. 註冊階段 2. 實例化階段 3. 初始化階段 4. 銷燬階段
註冊階段
註冊階段主要任務是經過各類BeanDefinitionReader讀取掃描各類配置來源信息(xml文件、註解等),並轉換爲BeanDefinition的過程。安全
BeanDefinition能夠理解爲類的定義,描述一個類的基本狀況,比較像咱們註冊某些網站時的基本信息,好比須要填寫姓名、住址、出生日期等。數據結構
最終會將咱們掃描到的類總體註冊到一個DefaultListableBeanFactory的Map容器中,便於咱們以後獲取使用。app
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { //存儲註冊信息的BeanDefinition private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256); //beanDefinitionMap的數據結構是ConcurrentHashMap,所以不能保證順序,爲了記錄註冊的順序,這裏使用了ArrayList類型beanDefinitionNames用來記錄註冊順序 private volatile List<String> beanDefinitionNames = new ArrayList<>(256); //省略部分代碼....... @Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { //省略判斷代碼....... // Still in startup registration phase this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName); } }
實例化階段
在實例化階段,Spring主要將BeanDefinition轉換爲實例Bean,並放在包裝類BeanWrapper中。框架
不管是否設置Bean的懶加載方式,最後都會經過AbstractBeanFactory.getBean()方法進行實例化,並進入到AbstractAutowireCapableBeanFactory.createBean()方法。ide
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { //省略部分代碼...... @Nullable protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { //實例化前處理器 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { //實例化後處理器 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean; } //省略部分代碼...... }
在實例化階段AbstractAutowireCapableBeanFactory.createBeanInstance()完成Bean的建立,並放到BeanWrapper中。源碼分析
初始化階段
初始化階段主要是在返回Bean以前作一些處理,主要由AbstractAutowireCapableBeanFactory.initializeBean()方法實現。post
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { //省略部分代碼...... //真正建立Bean的方法 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { //省略部分代碼...... // Initialize the bean instance. //Bean對象的初始化,依賴注入在此觸發 //這個exposedObject在初始化完成以後返回做爲依賴注入完成後的Bean Object exposedObject = bean; try { //將Bean實例對象封裝,而且Bean定義中配置的屬性值賦值給實例對象 populateBean(beanName, mbd, instanceWrapper); //初始化Bean對象 exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } //省略部分代碼...... return exposedObject; } //初始容器建立的Bean實例對象,爲其添加BeanPostProcessor後置處理器 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { //JDK的安全機制驗證權限 if (System.getSecurityManager() != null) { //實現PrivilegedAction接口的匿名內部類 AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { //爲Bean實例對象包裝相關屬性,如名稱,類加載器,所屬容器等信息 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; //對BeanPostProcessor後置處理器的postProcessBeforeInitialization //回調方法的調用,爲Bean實例初始化前作一些處理 if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } //調用Bean實例對象初始化的方法,這個初始化方法是在Spring Bean定義配置 //文件中經過init-method屬性指定的 try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } //對BeanPostProcessor後置處理器的postProcessAfterInitialization //回調方法的調用,爲Bean實例初始化以後作一些處理 if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; } //省略部分代碼...... }
銷燬階段
通常是在ApplicationContext關閉的時候調用,也就是AbstractApplicationContext.close() 方法。
在註冊的時候Spring經過適配器模式包裝了一個類DisposableBeanAdapter,在銷燬階段的時候會得到這個類,進而調用到DisposableBeanAdapter.destroy()方法:
class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { //省略部分代碼...... @Override public void destroy() { if (!CollectionUtils.isEmpty(this.beanPostProcessors)) { for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) { 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 { ((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) { invokeCustomDestroyMethod(this.destroyMethod); } else if (this.destroyMethodName != null) { Method methodToCall = determineDestroyMethod(this.destroyMethodName); if (methodToCall != null) { invokeCustomDestroyMethod(methodToCall); } } } //省略部分代碼...... }
銷燬階段主要包括三個銷燬途徑,按照執行順序:
- @PreDestroy註解,主要經過DestructionAwareBeanPostProcessor實現
- 實現DisposableBean接口,主要經過DisposableBean.destroy()實現
- 自定義銷燬方 DisposableBeanAdapter.invokeCustomDestroyMethod()實現
實例測試
下邊經過一個簡單實例來作一個簡單測試。
import org.springframework.beans.BeansException; import org.springframework.beans.factory.*; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; /** * @Author: maomao * @Date: 2021-04-18 20:50 */ public class User implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean, ApplicationContextAware, ApplicationEventPublisherAware { private String name; private int age; private BeanFactory beanFactory; private String beanName; public User(){ System.out.println("User【構造方法】默認構造方法!"); } public String getName() { return name; } public void setName(String name) { this.name = name; System.out.println("User【注入屬性】name " + name); } public int getAge() { return age; } public void setAge(int age) { this.age = age; System.out.println("User【注入屬性】age " + age); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("【BeanFactoryAware接口】調用setBeanFactory " + beanFactory); this.beanFactory = beanFactory; } @Override public void setBeanName(String name) { System.out.println("【BeanNameAware接口】setBeanName " + name); this.beanName = name; } @Override public void destroy() throws Exception { System.out.println("【DisposableBean接口】destroy"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("【InitializingBean接口】InitializingBean"); } public void initMethod(){ System.out.println("【initMethod方法】initMethod"); } public void destroyMethod(){ System.out.println("【destroyMethod方法】destroyMethod"); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("【ApplicationContextAware接口】setApplicationContext " + applicationContext); } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { System.out.println("【ApplicationEventPublisherAware接口】setApplicationEventPublisher " + applicationEventPublisher); } }
application.xml配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="beanPostProcessor" class="com.freecloud.spring.lifecycle.MyBeanPostProcessor"></bean> <bean id="instantiationAwareBeanPostProcessor" class="com.freecloud.spring.lifecycle.MyInstantiationAwareBeanPostProcessor"></bean> <bean id="beanFactoryPostProcessor" class="com.freecloud.spring.lifecycle.MyBeanFactoryPostProcessor"></bean> <bean id="user" class="com.freecloud.spring.lifecycle.User" init-method="initMethod" destroy-method="destroyMethod" > <property name="name" value="張三"></property> <property name="age" value="18"></property> </bean> </beans>
測試類:
import org.junit.Before; import org.junit.Test; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @Author: maomao * @Date: 2021-04-18 20:57 */ public class LifecycleTest { private ConfigurableApplicationContext applicationContext; @Before public void init(){ applicationContext = new ClassPathXmlApplicationContext("application.xml"); } @Test public void Test(){ User user = applicationContext.getBean("user",User.class); //ConfigurableApplicationContext.close()將關閉該應用程序的上下文,釋放全部資源,並銷燬全部緩存的單例bean // 只用於destroy演示 applicationContext.close(); //applicationContext.registerShutdownHook(); System.out.println("\n\n 輸出:" + user.getAge()); } }
最終結果: