距離上一次寫Spring源碼解析,已經過去了快要好幾個月了,主要原因還是Spring的源碼解析類文章太難寫了,不像我先前寫的什么CAS源碼,AQS源碼,LinkedBlockingQueue等等,這些無非就是分析幾個核心方法,代碼也不算太長,就像比較復雜的AQS源碼也是兩篇搞定的,雖然AQS源碼也很多東西也不能算是百分百的理解,但是核心思想應該是還算理解的。解析完畢成就感也滿滿的,寫完博客,看着大段大段的文字,心里也很開心:哈哈哈,原來JDK源碼也是可以讀懂的,而且還能寫出來。但是Spring源碼就不一樣了,如果和先前的源碼分析類文章一樣逐行去解析的話,那么可能一篇博客寫下來,一個小小小小小方法都沒法分析完,就算分析完畢了,也突出不了重點啊,但是Spring源碼解析還是要繼續的,就當做是自己的學習筆記把。
今天我們要看的內容是Spring Bean的生命周期,當然本篇博客只是帶着大家俯瞰下,不會進行過多的源碼分析,甚至只是貼下代碼,不做分析,只是找到Spring Bean生命周期的回調或者鈎子,當然這可能只是我的個人理解,大家還是要以懷疑的目光看待,也許我分析的是有問題的。
不知道Spring官方對Bean的生命問題是否有明確的定義或者解析,但是Spring In Action以及市面上流傳的大部分博客是這樣的:
- 實例化Bean對象,這個時候Bean的對象是非常低級的,基本不能夠被我們使用,因為連最基本的屬性都沒有設置,可以理解為連Autowired注解都是沒有解析的;
- 填充屬性,當做完這一步,Bean對象基本是完整的了,可以理解為Autowired注解已經解析完畢,依賴注入完成了;
- 如果Bean實現了BeanNameAware接口,則調用setBeanName方法;
- 如果Bean實現了BeanClassLoaderAware接口,則調用setBeanClassLoader方法;
- 如果Bean實現了BeanFactoryAware接口,則調用setBeanFactory方法;
- 調用BeanPostProcessor的postProcessBeforeInitialization方法;
- 如果Bean實現了InitializingBean接口,調用afterPropertiesSet方法;
- 如果Bean定義了init-method方法,則調用Bean的init-method方法;
- 調用BeanPostProcessor的postProcessAfterInitialization方法;當進行到這一步,Bean已經被准備就緒了,一直停留在應用的上下文中,直到被銷毀;
- 如果應用的上下文被銷毀了,如果Bean實現了DisposableBean接口,則調用destroy方法,如果Bean定義了destory-method聲明了銷毀方法也會被調用。
為了驗證上面的邏輯,可以做個試驗:
首先定義了一個Bean,里面有各種回調和鈎子,其中需要注意下,我在SpringBean的構造方法中打印了studentService,看SpringBean被new的出來的時候,studentService是否被注入了;又在setBeanName中打印了studentService,看此時studentService是否被注入了,以此來驗證,Bean是何時完成的自動注入的(這個StudentServiceImpl 類的代碼就不貼出來了,無非就是一個最普通的Bean):
public class SpringBean implements InitializingBean, DisposableBean, BeanNameAware, BeanFactoryAware, BeanClassLoaderAware {
public SpringBean() {
System.out.println("SpringBean構造方法:" + studentService);
System.out.println("SpringBean構造方法");
}
@Autowired
StudentServiceImpl studentService;
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet");
}
@Override
public void destroy() throws Exception {
System.out.println("destroy");
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("setBeanClassLoader");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("setBeanFactory");
}
@Override
public void setBeanName(String name) {
System.out.println("setBeanName:" + studentService);
System.out.println("setBeanName");
}
public void initMethod() {
System.out.println("initMethod");
}
public void destroyMethod() {
System.out.println("destroyMethod");
}
}
再定義一個BeanPostProcessor,在重寫的兩個方法中進行了判斷,如果傳進來的beanName是springBean才進行打印:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("springBean")) {
System.out.println("postProcessBeforeInitialization");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("springBean")) {
System.out.println("postProcessAfterInitialization");
}
return bean;
}
}
定義一個配置類,完成自動掃描,但是SpringBean是手動注冊的,並且聲明了initMethod和destroyMethod:
@Configuration
@ComponentScan
public class AppConfig {
@Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
public SpringBean springBean() {
return new SpringBean();
}
}
最后就是啟動類了:
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext =
new AnnotationConfigApplicationContext(AppConfig.class);
annotationConfigApplicationContext.destroy();
}
運行結果:
SpringBean構造方法:null
SpringBean構造方法
setBeanName:com.codebear.StudentServiceImpl@31190526
setBeanName
setBeanClassLoader
setBeanFactory
postProcessBeforeInitialization
afterPropertiesSet
initMethod
postProcessAfterInitialization
destroy
destroyMethod
可以看到,試驗結果和上面分析的完全一致。
這就是廣為流傳的Spring生命周期。
也許你在應付面試的時候,是死記硬背這些結論的,現在我帶着你找到這些方法,跟我來。
首先我們來到AnnotationConfigApplicationContext的構造方法:
//根據參數類型可以知道,其實可以傳入多個annotatedClasses,但是這種情況出現的比較少
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//調用無參構造函數,會先調用父類GenericApplicationContext的構造函數
//父類的構造函數里面就是初始化DefaultListableBeanFactory,並且賦值給beanFactory
//本類的構造函數里面,初始化了一個讀取器:AnnotatedBeanDefinitionReader read,一個掃描器ClassPathBeanDefinitionScanner scanner
//scanner的用處不是很大,它僅僅是在我們外部手動調用 .scan 等方法才有用,常規方式是不會用到scanner對象的
this();
//把傳入的類進行注冊,這里有兩個情況,
//傳入傳統的配置類
//傳入bean(雖然一般沒有人會這么做
//看到后面會知道spring把傳統的帶上@Configuration的配置類稱之為FULL配置類,不帶@Configuration的稱之為Lite配置類
//但是我們這里先把帶上@Configuration的配置類稱之為傳統配置類,不帶的稱之為普通bean
register(annotatedClasses);
//刷新
refresh();
}
進入refresh方法,refresh方法中有一個finishBeanFactoryInitialization小方法,這個方法是用來實例化懶加載單例Bean的,也就是我們的Bean都是在這里被創建出來的(當然我這里說的的是絕大部分情況是這樣的):
finishBeanFactoryInitialization(beanFactory);
我們再進入finishBeanFactoryInitialization這方法,里面有一個beanFactory.preInstantiateSingletons()方法:
//初始化所有的非懶加載單例
beanFactory.preInstantiateSingletons();
我們嘗試再點進去,這個時候你會發現這是一個接口,好在它只有一個實現類,所以可以我們來到了他的唯一實現,實現類就是org.springframework.beans.factory.support.DefaultListableBeanFactory,這里面是一個循環,我們的Bean就是循環被創建出來的,我們找到其中的getBean方法:
getBean(beanName);
這里有一個分支,如果Bean是FactoryBean,如何如何,如果Bean不是FactoryBean如何如何,好在不管是不是FactoryBean,最終還是會調用getBean方法,所以我們可以毫不猶豫的點進去,點進去之后,你會發現,這是一個門面方法,直接調用了doGetBean方法:
return doGetBean(name, null, null, false);
再進去,不斷的深入,接近我們要尋找的東西。
這里面的比較復雜,但是有我在,我可以直接告訴你,下一步我們要進入哪里,我們要進入
if (mbd.isSingleton()) {
//getSingleton中的第二個參數類型是ObjectFactory<?>,是一個函數式接口,不會立刻執行,而是在
//getSingleton方法中,調用ObjectFactory的getObject,才會執行createBean
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
這里面的createBean方法,再點進去啊,但是又點不進去了,這是接口啊,但是別慌,這個接口又只有一個實現類,所以說 沒事,就是干,這個實現類為org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory。
這個實現的方法里面又做了很多事情,我們就不去看了,我就是帶着大家找到那幾個生命周期的回調到底定義在哪里就OK了。
Object beanInstance = doCreateBean(beanName, mbdToUse, args);//創建bean,核心
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
再繼續深入doCreateBean方法,這個方法又做了一堆一堆的事情,但是值得開心的事情就是 我們已經找到了我們要尋找的東西了。
創建實例
首先是創建實例,位於:
instanceWrapper = createBeanInstance(beanName, mbd, args);//創建bean的實例。核心
填充屬性
其次是填充屬性,位於:
populateBean(beanName, mbd, instanceWrapper);//填充屬性,炒雞重要
在填充屬性下面有一行代碼:
exposedObject = initializeBean(beanName, exposedObject, mbd);
繼續深入進去。
aware系列接口的回調
aware系列接口的回調位於initializeBean中的invokeAwareMethods方法:
invokeAwareMethods(beanName, bean);
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
BeanPostProcessor的postProcessBeforeInitialization方法
BeanPostProcessor的postProcessBeforeInitialization方法位於initializeBean的
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
afterPropertiesSet init-method
afterPropertiesSet init-method位於initializeBean中的
invokeInitMethods(beanName, wrappedBean, mbd);
這里面調用了兩個方法,一個是afterPropertiesSet方法,一個是init-method方法:
((InitializingBean) bean).afterPropertiesSet();
invokeCustomInitMethod(beanName, bean, mbd);
BeanPostProcessor的postProcessAfterInitialization方法
BeanPostProcessor的postProcessAfterInitialization方法位於initializeBean的
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
當然在實際的開發中,應該沒人會去銷毀Spring的應用上下文把,所以剩余的兩個銷毀的回調就不去找了。
這就是廣為流傳的Spring Bean的生命周期,我也帶着大家找到了各種回調和鈎子,但是我認為這並非是Spring Bean完整的生命周期,只是經過簡化的,那么我認為的完整的生命周期是如何的呢,請聽下回分解。