- 本文是一篇spring源碼相關的文章。衆所周知,讀源碼是一件使人恐懼的事情,看源碼相關的博客、書和文章亦是如此。(筆者曾經狂啃mybatis的設計與實現這本書,結果是看着超級痛苦,看完之後沒留下啥印象)。鑑於此,本文的源碼解析就不按照傳統的去貼代碼的方式去講解spring源碼了,本文的源碼解析以流程的方式來說解spring在每一步都幹了什麼,因此謂之曰spring源碼導讀。。。。
- 在正式開始spring源碼導讀以前,讀者總得知道spring裏的各個標籤是幹啥的吧,所以文中前一部分羅列了spring常見的註解用法。並搞了點SpringAOP和spring事務源碼的解析做爲後面正式開始的導讀的開胃菜
- 介紹完了,讓咱們開始吧!!!。
spring註解
ApplicationContextProcessor.java
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware)bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
}
}
}
Bean生命週期:
初始化和銷燬數組
- 經過@Bean 指定init-method和destroy-method
- 實現InitializingBean定義初始化邏輯,實現DisposableBean定義銷燬方法
- 實現BeanPostProcessor接口的後置攔截器放入容器中,能夠攔截bean初始化,並能夠在被攔截的Bean的初始化先後進行一些處理工做。
spring底層經常使用的BeanPostProcessor:mybatis
* BeanValidationPostProcessor用來實現數據校驗
* AutowireAnnotationBeanPostProcessor,@Autowire實現
* ApplicationContextProcessor實現XXXAware的自動注入。
執行時機app
doCreateBean
-populateBean():給bean的各類屬性賦值
-initializeBean():初始化bean
-處理Aware方法
-applyBeanPostProcessorsBeforeInitialization:後置處理器的實例化前攔截
-invokeInitMethods:執行@Bean指定的initMethod
-applyBeanPostProcessorsAfterInitialization:後置處理器的實例化後攔截
SpringAOP實現原理
使用步驟異步
- @EnableAspectJAutoProxy 開啓基於註解的aop模式
- @Aspect:定義切面類,切面類裏定義通知
- @PointCut 切入點,能夠寫切入點表達式,指定在哪一個方法切入
-
通知方法函數
- @Before(前置通知)
- @After(後置通知)
- @AfterReturning(返回通知)
- @AfterTrowing(異常通知)@Around(環繞通知)
- JoinPoint:鏈接點,是一個類,配合通知使用,用於獲取切入的點的信息
SpringAop原理post
-
@EnableAspectJAutoProxyui
- @EnableAspectJAutoProxy 經過@Import(AspectJAutoProxyRegistrar.class)給spring容器中導入了一個AnnotationAwareAspectJAutoProxyCreator。
- AnnotationAwareAspectJAutoProxyCreator實現了InstantiationAwareBeanPostProcessor,InstantiationAwareBeanPostProcessor是一個BeanPostProcessor。它能夠攔截spring的Bean初始化(Initialization)先後和實例化(Initialization)先後。
- AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation(bean實例化前):會經過調用isInfrastructureClass(beanClass)來判斷 被攔截的類是不是基礎類型的Advice、PointCut、Advisor、AopInfrastructureBean,或者是不是切面(@Aspect),如果則放入adviseBean集合。這裏主要是用來處理咱們的切面類。
-
AnnotationAwareAspectJAutoProxyCreator的BeanPostProcessorsAfterInitialization(bean初始化後):this
- 首先找到被攔截的Bean的匹配的加強器(通知方法),這裏有切入點表達式匹配的邏輯
- 將加強器保存到proxyFactory中,
- 根據被攔截的Bean是否實現了接口,spring自動決定使用JdkDynamicAopProxy仍是ObjenesisCglibAopProxy
- 最後返回被攔截的Bean的代理對象,註冊到spring容器中
-
代理Bean的目標方法執行過程:CglibAopProxy.intercept();
- 保存全部的加強器,並處理轉換爲一個攔截器鏈
- 若是沒有攔截器鏈,就直接執行目標方法
- 若是有攔截器鏈,就將目標方法,攔截器鏈等信息傳入並建立CglibMethodInvocation對象,並調用proceed()方法獲取返回值。proceed方法內部會依次執行攔截器鏈。
spring 聲明式事務
基本步驟
- 配置數據源:DataSource
- 配置事務管理器來控制事務:PlatformTransactionManager
- @EnableTransactionManagement開啓基於註解的事務管理功能
- 給方法上面標註@Transactional標識當前方法是一個事務方法
聲明式事務實現原理
- @EnableTransactionManagement利用TransactionManagementConfigurationSelector給spring容器中導入兩個組件:AutoProxyRegistrar和ProxyTransactionManagementConfiguration
- AutoProxyRegistrar給spring容器中註冊一個InfrastructureAdvisorAutoProxyCreator,InfrastructureAdvisorAutoProxyCreator實現了InstantiationAwareBeanPostProcessor,InstantiationAwareBeanPostProcessor是一個BeanPostProcessor。它能夠攔截spring的Bean初始化(Initialization)先後和實例化(Initialization)先後。利用後置處理器機制在被攔截的bean建立之後包裝該bean並返回一個代理對象代理對象執行方法利用攔截器鏈進行調用(同springAop的原理)
-
ProxyTransactionManagementConfiguration:是一個spring的配置類,它爲spring容器註冊了一個BeanFactoryTransactionAttributeSourceAdvisor,是一個事務事務加強器。它有兩個重要的字段:AnnotationTransactionAttributeSource和TransactionInterceptor。
- AnnotationTransactionAttributeSource:用於解析事務註解的相關信息
- TransactionInterceptor:事務攔截器,在事務方法執行時,都會調用TransactionInterceptor的invoke->invokeWithinTransaction方法,這裏面經過配置的PlatformTransactionManager控制着事務的提交和回滾。
Spring 擴展(鉤子)
- BeanFactoryPostProcessor:beanFactory後置處理器,的攔截時機:全部Bean的定義信息已經加載到容器,但尚未被實例化。能夠對beanFactory進行一些操做。
- BeanPostProcessor:bean後置處理器,攔截時機:bean建立對象初始化先後進行攔截工做。能夠對每個Bean進行一些操做。
- BeanDefinitionRegistryPostProcessor:是BeanFactoryPostProcessor的子接口,攔截時機:全部Bean的定義信息已經加載到容器,但尚未被實例化,能夠對每個Bean的BeanDefinition進行一些操做。
-
ApplicationListener,自定義ApplicationListener實現類並加入到容器中,能夠監聽spring容器中發佈的事件。spring在建立容器的時候(finishRefresh()方法)會發布ContextRefreshedEvent事件,關閉的時候(doClose())會發布ContextClosedEvent事件。也能夠經過spring容器的publishEvent發佈本身的事件。
-
事件發佈流程:publishEvent方法
- 獲取事件的多播器,getApplicationEventMulticaster()。
- 調用multicastEvent(applicationEvent, eventType)派發事件。獲取到全部的ApplicationListener,即getApplicationListeners(),而後同步或者異步的方式執行監聽器的onApplicationEvent。
- 事件的多播器的初始化中(initApplicationEventMulticaster()),若是容器中沒有配置applicationEventMulticaster,就使用SimpleApplicationEventMulticaster。而後獲取全部的監聽器,並把它們註冊到SimpleApplicationEventMulticaster中。
- @EventListener(class={}):在普通的業務邏輯的方法上監聽事件特定的事件。原理:EventListenerMethodProcessor是一個SmartInitializingSingleton,當全部的單例bean都初始化完之後, 容器會回調該接口的方法afterSingletonsInstantiated(),該方法裏會遍歷容器中全部的bean,並判斷每個bean裏是否帶有@EventListener註解的Method,而後建立ApplicationListenerMethodAdapter存儲幷包裝該Method,最後將ApplicationListenerMethodAdapter添加到spring容器中。
Spring源代碼分析
spring核心邏輯AbstractApplicationContext的refresh()方法以下
public void refresh() {
synchronized (this.startupShutdownMonitor) {
// 刷新前的預準備工做
prepareRefresh();
// 提取bean的配置信息並封裝成BeanDefinition實例,而後將其添加到註冊中心。註冊中心是一個ConcurrentHashMap<String,BeanDefinition>類型,key爲Bean的名字,value爲BeanDefinition實例。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//對beanFactory進行一些配置,註冊一些BeanPostProcessor和一些特殊的Bean。
prepareBeanFactory(beanFactory);
//留給子類在BeanFactory準備工做完成後處理一些工做。
postProcessBeanFactory(beanFactory);
//調用 BeanFactory的後置處理器。
invokeBeanFactoryPostProcessors(beanFactory);
//註冊Bean的後置處理器。
registerBeanPostProcessors(beanFactory);
//國際化相關功能
initMessageSource();
//初始化事件派發器;
initApplicationEventMulticaster();
// 提供給子容器類,供子容器去實例化其餘的特殊的Bean
onRefresh();
// 處理容器中已有的ApplicationListener
registerListeners();
//初始化容器中剩餘的單實例bean
finishBeanFactoryInitialization(beanFactory);
//最後一步
finishRefresh();
}
}
prepareRefresh()
1. 記錄啓動時間,設置容器的active和close狀態。
2. initPropertySources():提供給子容器類,子容器類可覆蓋該方法進行一些自定義的屬性設置。
3. getEnvironment().validateRequiredProperties():檢驗屬性的合法性
4. this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>() :保存容器中的一些早期的事件,待事件多播器建立後執行。
obtainFreshBeanFactory()
提取bean的配置信息並封裝成BeanDefinition實例,而後將其添加到註冊中心。註冊中心是一個ConcurrentHashMap<String,BeanDefinition>類型,key爲Bean的名字,value爲BeanDefinition實例。
1. refreshBeanFactory:若是當前容器已經有了BeanFactory就銷燬原來的BeanFactory。而後建立一個DefaultListableBeanFactory();
* 對BeanFactory並進行配置,主要配置是否容許BeanDefinition覆蓋,是否容許Bean間的循環引用。
* 加載BeanDefinition,解析XML文件和配置文件,將其轉換爲BeanDefinition,而後保存到DefaultListableBeanFactory的beanDefinitionMap字段中。
2. getBeanFactory() 簡單的返回beanFactory,即DefaultListableBeanFactory。
prepareBeanFactory()
1. 設置BeanFactory的類加載器、設置支持SPEL表達式的解析器。
2. 添加ApplicationContextAwareProcessor用於處理XXXAware接口的回調。
3. 設置忽略一些接口。並註冊一些類,這些類能夠在bean裏直接進行自動裝配。
4. 添加ApplicationListenerDetector用於識別並保存ApplicationListener的子類。
postProcessBeanFactory():
提供給子容器類,子容器類能夠覆蓋該方法在BeanFactory準備工做完成後處理一些工做。
invokeBeanFactoryPostProcessors()
執行BeanFactoryPostProcessor類型的監聽方法。
* BeanFactoryPostProcessor是beanFactory後置處理器,在整個BeanFactory標準初始化完成後進行攔截調用,
* BeanDefinitionRegistryPostProcessor繼承了BeanFactoryPostProcessor,在beanFactory解析完全部的BeanDefinition後攔截調用。
* BeanFactoryPostProcessor來源
* 經過ApplicationContent的addBeanFactoryPostProcessor()方法手動添加本身的攔截器
* 系統默認了一些BeanFactoryPostProcessor。例如:ConfigurationClassPostProcessor用來處理@Configuration標註的Spring配置類。
* 調用順序
1. 先調用BeanDefinitionRegistryPostProcessor類型的攔截器,
2. 而後再依次調用實現了PriorityOrdered,Ordered接口的BeanFactoryPostProcessor
3. 最後調用普通的BeanFactoryPostProcessor
registerBeanPostProcessors()
註冊Bean的後置處理器。
1. 從beanFactory裏獲取全部BeanPostProcessor類型的Bean的名稱。
2. 調用beanFactory的getBean方法並傳入每個BeanPostProcesso類型的Bean名稱,從容器中獲取該Bean的實例。
3.
1. 第一步向beanFactory註冊實現了PriorityOrdered的BeanPostProcessor類型的Bean實例。
2. 第二步向beanFactory註冊實現了Ordered的BeanPostProcessor類型的Bean實例。
3. 第三步向beanFactory註冊普通的BeanPostProcessor類型的Bean實例。
4. 最後一步向beanFactory從新註冊實現了MergedBeanDefinitionPostProcessor的BeanPostProcessor類型的Bean實例
4. 向beanFactory註冊BeanPostProcessor的過程就是簡單的將實例保存到beanFactory的beanPostProcessors屬性中。
initMessageSource()
國際化相關功能
1. 看容器中是否有id爲messageSource的,類型是MessageSource的Bean實例。若是有賦值給messageSource,若是沒有本身建立一個DelegatingMessageSource。
2. 把建立好的MessageSource註冊在容器中,之後獲取國際化配置文件的值的時候,能夠自動注入MessageSource。
initApplicationEventMulticaster()
初始化事件派發器;
1. 看容中是否有名稱爲applicationEventMulticaster的,類型是ApplicationEventMulticaster的Bean實例。若是沒有就建立一個SimpleApplicationEventMulticaster。
2. 把建立好的ApplicationEventMulticaster添加到BeanFactory中。
onRefresh():
提供給子容器類,供子容器去實例化其餘的特殊的Bean。
registerListeners():
處理容器中已有的ApplicationListener。
1. 從容器中得到全部的ApplicationListener
2. 將每一個監聽器添加到事件派發器(ApplicationEventMulticaster)中;
3. 處理以前步驟產生的事件;
finishBeanFactoryInitialization():
初始化容器中剩餘的單實例bean:拿到剩餘的全部的BeanDefinition,依次調用getBean方法(詳看beanFactory.getBean的執行流程)
finishRefresh():
最後一步。
1. 初始化和生命週期有關的後置處理器;LifecycleProcessor,若是容器中沒有指定處理就建立一個DefaultLifecycleProcessor加入到容器。
2. 獲取容器中全部的LifecycleProcessor回調onRefresh()方法。
3. 發佈容器刷新完成事件ContextRefreshedEvent。
ConfigurationClassPostProcessor處理@Configuration的過程:
- 先從主從中心取出全部的BeanDefinition。依次判斷,若一個BeanDefinition是被@Configuration標註的,spring將其標記爲FullMode,不然若一個BeanDefinition沒有被@Configuration標註,但有被@Bean標註的方法,spring將其標記爲LightMode。篩選出全部候選配置BeanDefinition(FullMode和LightMode)
-
建立一個ConfigurationClassParser,調用parse方法解析每個配置類。
- 解析@PropertySources,將解析結果設置到Environment
- 利用ComponentScanAnnotationParser,將@ComponentScans標籤解析成BeanDefinitionHolder。再迭代解析BeanDefinitionHolder
- 解析@Import,@ImportResource
- 將@Bean解析爲MethodMetadata,將結果保存到ConfigurationClass中。最終ConfigurationClass會被保存到ConfigurationClassParser的configurationClasses中。
-
調用ConfigurationClassParser的loadBeanDefinitions方法,加載解析結果到註冊中。
- 從利用ComponentScanAnnotationParser的configurationClasses獲取全部的ConfigurationClass,依次調用loadBeanDefinitionsForConfigurationClass方法。
- loadBeanDefinitionsForConfigurationClass會將每個BeanMethod轉爲ConfigurationClassBeanDefinition,最後將其添加到spring的註冊中心。
beanFactory.getBean方法執行的過程
- 首先將方法傳入的beanName進行轉換:先去除FactoryBean前綴(&符)若是傳遞的beanName是別名,則經過別名找到bean的原始名稱。
- 根據名稱先從singletonObjects(一個Map類型的容)獲取bean實例。若是能獲取到就先判斷該bean實例是否實現了FactoryBean,若是是FactoryBean類型的bean實例,就經過FactoryBean獲取Bean。而後直接返回該bean實例。getBean方法結束。
-
若是從singletonObjects沒有獲取到bean實例就開始建立Bean的過程。
- 首先標記該Bean處於建立狀態。
- 根據Bean的名稱找到BeanDefinition。查看該Bean是否有前置依賴的Bean。如有則先建立該Bean前置依賴的Bean。
- spring調用AbstractAutowireCapableBeanFactory的createBean方法並傳入BeanDefinition開始建立對象。先調用resolveBeforeInstantiation給BeanPostProcessor一個機會去返回一個代理對象去替代目標Bean的實例。
-
若是BeanPostProcessor沒有返回Bean的代理就經過doCreateBean方法建立對象。
- 首先肯定Bean的構造函數,若是有有參構造器,先自動裝配有參構造器,默認使用無參數構造器。
- 選擇一個實例化策略去實例化bean。默認使用CglibSubclassingInstantiationStrategy。該策略模式中,首先判斷bean是否有方法被覆蓋,若是沒有則直接經過反射的方式來建立,若是有的話則經過CGLIB來實例化bean對象. 把建立好的bean對象包裹在BeanWrapper裏。
- 調用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition
- 判斷容器是否容許循環依賴,若是容許循環依賴,就建立一個ObjectFactory類並實現ObjectFactory接口的惟一的一個方法getObject()用於返回Bean。而後將該ObjectFactory添加到singletonFactories中。
- 調用populateBean爲bean實例賦值。在賦值以前執行InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation和postProcessPropertyValues方法。
- 調用initializeBean初始化bean。若是Bean實現了XXXAware,就先處理對應的Aware方法。而後調用beanProcessor的postProcessBeforeInitialization方法。再以反射的方式調用指定的bean指定的init方法。最後調用beanProcessor的postProcessAfterInitialization方法。
- 調用registerDisposableBeanIfNecessary,將該bean保存在一個以beanName爲key,以包裝了bean引用的DisposableBeanAdapter,爲value的map中,在spring容器關閉時,遍歷這個map來獲取須要調用bean來依次調用Bean的destroyMethod指定的方法。
- 將新建立出來的Bean保存到singletonObjects中
spring原理補充
spring解決循環依賴
以類A,B互相依賴注入爲例
- 根據類A的名稱先從singletonObjects獲取Bean實例,發現獲取不到,就經過doGetBean方法開始建立Bean的流程。
- 根據A的名稱找到對應的BeanDefinition,經過doCreateBean()方法建立對象,先肯定類A的構造函數,而後選擇一個實例化策略去實例化類A。
- 判斷容器是否容許循環依賴,若是容許循環依賴,就建立一個ObjectFactory類並實現ObjectFactory接口的惟一的一個方法getObject()用於返回類A。而後將該ObjectFactory添加到singletonFactories中。
-
調用populateBean()爲類A進行屬性賦值,發現須要依賴類B,此時類B還沒有建立,啓動建立類B的流程。
- 根據類B的名稱先從singletonObjects獲取Bean實例,發現獲取不到,就開始經過doGetBean方法開始建立Bean的流程
- 找到類B對應的BeanDefinition,確認B的構造函數,而後實例化B。
- 判斷容器是否容許循環依賴,建立一個ObjectFactory並實現getObject()方法,用於返回類B,並添加到singletonFactories中。
- 調用populateBean()爲類B進行屬性賦值,發現須要依賴類A,調用getSingleton方法獲取A:A如今已存在於singletonFactories中,getSingleton將A從singletonFactories方法中移除並放入earlySingletonObjects中。
- 調用getSingleton()方法獲取B:getSingleton將A從singletonFactories方法中移除並放入earlySingletonObjects中。
- 調用initializeBean初始化bean,最後將新建立出來的類B保存到singletonObjects中
- 調用getSingleton()方法獲取A,這時A已在earlySingletonObjects中了,就直接返回A
- 調用initializeBean初始化bean,最後將新建立出來的類B保存到singletonObjects中。
@Autowire 實現原理
上面介紹beanFactory.getBean方法執行的過程中提到:populateBean爲bean實例賦值。在賦值以前執行InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation和postProcessPropertyValues方法。@Autowire由AutowiredAnnotationBeanPostProcessor完成,它實現了InstantiationAwareBeanPostProcessor。
AutowiredAnnotationBeanPostProcessor執行過程:
- postProcessAfterInstantiation方法執行,直接return null。
- postProcessPropertyValues方法執行,主要邏輯在此處理。待補充。。。。。