Spring5.0原始碼深度解析之SpringBean的生命週期
SpringBean的生命週期
一:單例與多例物件是如何初始化
單例預設情況下是在容器被載入的時候就會初始化
多例是在每次獲取Bean物件的時候初始化
程式碼驗證:
@Component public class UserEntity { public UserEntity() { System.out.println(">>>>UserEntity無引數建構函式執行..."); }
@Configuration @ComponentScan("com.mayikt.entity") public class MyConfig { }
>>>>UserEntity無引數建構函式執行...
當加上@Scope("prototype"),沒有輸出結果
@Component @Scope("prototype") public class UserEntity { public UserEntity() { System.out.println(">>>>UserEntity無引數建構函式執行..."); }
說明單例預設是在容器被載入的時候初始化,多例是在每次獲取Bean物件的時候初始化。
二:Bean物件的初始化與銷燬過程01
Bean初始化:指的就是物件已經建立,裡面的所有set方法都已經執行完畢了。
舉個例子:
@Configuration @ComponentScan("com.mayikt.entity") public class MyConfig { /** * initMethod:指定初始化方法執行 * destroyMethod:指定銷燬方法 * @return */ @Bean(initMethod = "initMethod",destroyMethod = "destroyMethod") public UserEntity userEntity(){ return new UserEntity(); } }
@Component public class UserEntity { public UserEntity() { System.out.println(">>>>UserEntity無引數建構函式執行..."); } /** * 思考:initMethod是在無參建構函式之前執行還是後執行.. */ private void initMethod() { System.out.println(">>>>UserEntity initMethod 執行..."); } private void destroyMethod() { System.out.println(">>>>UserEntity destroyMethod 執行..."); } }
public static void main(String[] args) { /** * IOC容器初始化單例物件都是迴圈遍歷呼叫getBean方法 */ AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class); applicationContext.close();
返回結果
>>>>UserEntity無引數建構函式執行...
>>>>UserEntity initMethod 執行...
>>>>UserEntity destroyMethod 執行...
建構函式:Bean的建立,Map集合儲存物件
initMethod:表示物件已經建立成功之後執行
destroyMethod:表示物件被銷燬之後執行,clean
destroyMethod方法執行時,相當於呼叫了close方法去銷燬Bean
applicationContext.close();
public void close() {
synchronized (this.startupShutdownMonitor) {
doClose();
// If we registered a JVM shutdown hook, we don't need it anymore now:
// We've already explicitly closed the context.
if (this.shutdownHook != null) {
try {
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
}
catch (IllegalStateException ex) {
// ignore - VM is already shutting down
}
}
}
}
protected void doClose() {
if (this.active.get() && this.closed.compareAndSet(false, true)) {
....
// Destroy all cached singletons in the context's BeanFactory.
destroyBeans();
// Close the state of this context itself.
closeBeanFactory();
// Let subclasses do some final clean-up if they wish...
onClose();
this.active.set(false);
}
}
protected void destroyBeans() { getBeanFactory().destroySingletons(); }
public void destroySingletons() { super.destroySingletons(); this.manualSingletonNames.clear(); this.clearByTypeCache(); }
private void clearByTypeCache() { this.allBeanNamesByType.clear(); this.singletonBeanNamesByType.clear(); }
上面執行了clear操作,再回到前面
這裡給使用者自定義關閉操作:模板方法設計模式
protected void onClose() { // For subclasses: do nothing by default. }
再把活躍狀態設定為false。
三:Bean物件的初始化與銷燬過程02
1.實現InitializingBean,DisposableBean兩個介面
@Component public class MemberEntity implements InitializingBean,DisposableBean{ // implements InitializingBean, DisposableBean public MemberEntity() { System.out.println("無參建構函式執行.."); } // afterPropertiesSet initMet hod // 1.物件建立 物件屬性賦值 set方法全部走完 @Override public void afterPropertiesSet() throws Exception { System.out.println("MemberEntity >>>afterPropertiesSet"); } @Override public void destroy() throws Exception { System.out.println("MemberEntity >>> destroy"); } }
輸出結果:
無參建構函式執行..
MemberEntity >>>afterPropertiesSet
MemberEntity >>> destroy
2.使用Java封裝的註解方式@PostConstruct, @PreDestroy
@Component public class MemberEntity{ // implements InitializingBean, DisposableBean public MemberEntity() { System.out.println("無參建構函式執行.."); } // afterPropertiesSet initMet hod // 1.物件建立 物件屬性賦值 set方法全部走完 @PostConstruct public void afterPropertiesSet() throws Exception { System.out.println("MemberEntity >>>afterPropertiesSet"); } @PreDestroy public void destroy() throws Exception { System.out.println("MemberEntity >>> destroy"); } }
輸出結果
無參建構函式執行..
MemberEntity >>>afterPropertiesSet
MemberEntity >>> destroy
四:現在我們開始分析SpringBean的生命週期
SpringBean生命週期有個很好的理念就是後置處理器BeanPostProcessor
後置處理器:BeanPostProcessor
BeanPostProcessor引入:
@Component public class MyApplicationContext implements ApplicationContextAware { private ApplicationContext applicationContext; /** * spring底層中為什麼能夠實現ApplicationContextAware介面 就能夠拿到ApplicationContext * @param applicationContext * @throws BeansException */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { MemberEntity memberEntity = applicationContext.getBean("memberEntity", MemberEntity.class); System.out.println("memberEntity:" + memberEntity); } }
@Configuration @ComponentScan("com.mayikt.entity") @Import(MyApplicationContext.class)//這裡注入到spring容器中 public class MyConfig {}
輸出結果:物件初始化,賦值完畢,就可以通過setApplicationContext拿到bean物件
memberEntity:com.mayikt.entity.MemberEntity@11e21d0e
思考問題:spring底層中為什麼能夠實現ApplicationContextAware介面 就能夠拿到ApplicationContext
關鍵就是在於:BeanPostProcessor
下面我們開始分析:BeanPostProcessor後置處理器(非常重要!!!)
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
....
try {
....
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
}
....
}
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
....
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
@Override
public void preInstantiateSingletons() throws BeansException {
....
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) () ->
((SmartFactoryBean<?>) factory).isEagerInit(),
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
....
}
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { .... Object sharedInstance = getSingleton(beanName);//檢測快取中或者例項工廠中是否有對應的例項 if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);//返回對應的例項,有時候存在諸如BeanFactory的情況並不是直接返回例項本身而是返回指定方法返回的例項 } else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) {//只有在單例情況下才會去嘗試解決迴圈依賴 throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {//如果beaanDefinitionMap中也就是在所有已經載入的類中不包括beanName則嘗試從parentBeanFactory中檢測 // Not found -> check parent. String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) {//遞迴到BeanFactory中尋找 // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) {//如果不是僅僅做型別檢查,則是建立Bean,這裡進行記錄 markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);//轉換為RootBeanDefinition checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) {//若存在依賴則需要遞迴例項化依賴的Bean for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName);//快取依賴呼叫 getBean(dep); } } // Create bean instance. if (mbd.isSingleton()) {//例項化依賴的bean後,便可例項化mbd本身了,單例模式的建立 sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) {//prototype模式的建立 // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // Check if required type matches the type of the actual bean instance. if (requiredType != null && !requiredType.isInstance(bean)) {//檢測需要的型別是否符合實際bean的型別 try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { if (logger.isDebugEnabled()) { logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }
步驟大致如下:
1.轉換BeanName
2.嘗試從快取中載入單例bean
3.Bean的例項化
4.原型模式的依賴檢查
5.檢查parentBeanFactory
6.將儲存XML配置檔案的GernericBeanDefinition轉換為RootBeanDefinition
7.尋找依賴
8.針對不同的scope進行bean的建立
9.型別轉換
判斷是單例:
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
....
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
....
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { final Object bean = instanceWrapper.getWrappedInstance(); .... Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper);//迴圈給屬性賦值 exposedObject = initializeBean(beanName, exposedObject, mbd); } .... }
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);//執行自定義的init方法 } 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; }
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) { //判斷型別並設定beanName
((BeanNameAware)bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = this.getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware)bean).setBeanFactory(this);
}
}
}
我們就明白了:IOC容器初始化單例物件都是迴圈遍歷呼叫getBean方法。
下面我們手寫看下springBean的生命週期
@Component public class PayEntity implements BeanNameAware, BeanFactoryAware, InitializingBean, ApplicationContextAware { public PayEntity() { System.out.println("1.物件的例項化完成.."); } @Override public void setBeanName(String name) { System.out.println("2.物件beanName:" + name); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("3.beanFactory:" + beanFactory); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("4.獲取到applicationContext物件"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("5.bean init方法執行.."); }
輸出結果
1.物件的例項化完成..
2.物件beanName:payEntity
3.beanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory@55f3ddb1: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,myConfig,payEntity]; root of factory hierarchy
4.獲取到applicationContext物件
5.bean init方法執行..
BeanPostProcessor的作用
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { .... if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);//init之前處理操作 } .... try { invokeInitMethods(beanName, wrappedBean, mbd);//init執行邏輯 } .... if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);//init之後處理操作 } return wrappedBean; }
BeanPostProcessor後置處理器的前置處理邏輯和後置處理邏輯:
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
...
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
...
}
我們自定義類實現BeanPostProcessor
@Component public class MyBeanPostProcessor implements BeanPostProcessor { //BeanPostProcessor 後置處理器 對我們bean的物件實現增強 @Override // 執行自定義init方法之前處理 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("執行init方法之前處理 : " + beanName); return bean; } @Override // 執行自定義init方法之後處理 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("執行init方法之後處理 :" + beanName); return bean; } //BeanPostProcessor 後置處理 // Aware 實現 }
輸出結果:
執行init方法之前處理 : org.springframework.context.event.internalEventListenerProcessor
執行init方法之後處理 :org.springframework.context.event.internalEventListenerProcessor
執行init方法之前處理 : org.springframework.context.event.internalEventListenerFactory
執行init方法之後處理 :org.springframework.context.event.internalEventListenerFactory
執行init方法之前處理 : myConfig
執行init方法之後處理 :myConfig
1.物件的例項化完成..
2.物件beanName:payEntity
3.beanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory@55f3ddb1: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,myConfig,payEntity,com.mayikt.processor.MyBeanPostProcessor]; root of factory hierarchy
4.獲取到applicationContext物件
執行init方法之前處理 : payEntity
5.bean init方法執行..
執行init方法之後處理 :payEntity
ApplicationAware介面原理
實現ApplicationAware介面怎麼就可以setApplicationContext呢?
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("4.獲取到applicationContext物件"); }
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
發現BeanPostProcessor後置處理器的postProcessAfterInitialization後置處理什麼也沒做:
再去前置找:
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException { AccessControlContext acc = null; if (System.getSecurityManager() != null && (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) { acc = this.applicationContext.getBeanFactory().getAccessControlContext(); } if (acc != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareInterfaces(bean); return null; }, acc); } else { invokeAwareInterfaces(bean); } return bean; }
private void invokeAwareInterfaces(Object bean) { if (bean instanceof Aware) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) {//判斷ApplicationContextAware型別,賦值 ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } } }
看到沒有,最後判斷:bean instanceof ApplicationContextAware型別,再賦值
我們就可以知道上面提出的這個問題:實現ApplicationAware介面怎麼就可以setApplicationContext?
所以我們知道ApplicationContextAware是通過BeanPostProcessor後置處理器的postProcessBeforeInitialization前置處理實現的。
SpringBean的生命週期總結
原始碼分析流程:
1.進入到重新整理refresh()方法
2.finishBeanFactoryInitialization()初始化所有單例物件
3.preInstantiateSingletons()初始化所有的單例物件:注意是非懶載入
4.getBean()-》doGetBean()先查詢該物件是否有初始化過,沒有的化就建立註冊到IOC容器中
5.createBean()判斷物件如果是單例的情況下,就呼叫該方法去建立物件
6.doCreateBean()建立IOC物件
7.createBeanInstance()使用Java的反射機制例項化我們的物件
8.populateBean()給物件的set屬性賦值
9.initializeBean()執行初始化方法(也可以自己定義初始化的方法)
10.invokeAwareMethods()判斷bean的型別是否是Aware相關依賴,如果存在的情況回撥方法
11.applyBeanPostProcessorsBeforeInitialization()在初始化方法之前執行處理(增強)
12.invokeInitMethods()呼叫自定義的init方法,Java反射技術
13.applyBeanPostProcessorsAfterInitialization()在初始化方法之後執行處理(增強)
14.正常是用我們初始化好的這個Bean物件
15.銷燬bean
本文參考
參考書籍:Spring原始碼深度解析
螞蟻課堂:http://www.mayikt.co