spring源碼導讀:別怕,文章裏沒有貼代碼

  1. 本文是一篇spring源碼相關的文章。衆所周知,讀源碼是一件使人恐懼的事情,看源碼相關的博客、書和文章亦是如此。(筆者曾經狂啃mybatis的設計與實現這本書,結果是看着超級痛苦,看完之後沒留下啥印象)。鑑於此,本文的源碼解析就不按照傳統的去貼代碼的方式去講解spring源碼了,本文的源碼解析以流程的方式來說解spring在每一步都幹了什麼,因此謂之曰spring源碼導讀。。。。
  2. 在正式開始spring源碼導讀以前,讀者總得知道spring裏的各個標籤是幹啥的吧,所以文中前一部分羅列了spring常見的註解用法。並搞了點SpringAOP和spring事務源碼的解析做爲後面正式開始的導讀的開胃菜
  3. 介紹完了,讓咱們開始吧!!!。

spring註解

  • @Configuration 用於標註配置類
  • @Bean 結合@Configuration(full mode)使用或結合@Component(light mode)使用。能夠導入第三方組件,入方法有參數默認從IOC容器中獲取,能夠指定initMethod和destroyMethod 指定初始化和銷燬方法,多實例對象不會調用銷燬方法.
  • 包掃描@ComponentScan (@ComponentScans能夠配置多個掃描,@TypeFilter:指定過濾規則,本身實現TypeFilter類)
    組件(@Service、@Controller、@Repository):包掃描+組件註解導入註解。
  • @Scope:設置組件做用域 1.prototype:多例的2.singleton:單例的(默認值)
  • @Lazy 懶加載
  • @Conditional({Condition}):按照必定的條件進行判斷,知足條件給容器中註冊Bean,傳入Condition數組,,使用時需本身建立類繼承Condition而後重寫match方法。
  • @Import[快速給容器中導入一個組件]java

    1. Import(類名),容器中就會自動註冊這個組件,id默認是組件的全名
    2. ImportSelector:返回須要導入的組件的全類名的數組
    3. ImportBeanDefinitionRegistrar:手動註冊bean
  • FactoryBean:工廠Bean,交給spring用來生產Bean到spring容器中.能夠經過前綴&來獲取工廠Bean自己.
  • @Value:給屬性賦值,也可使用SpEL和外部文件的值
  • @PropertySource:讀取外部配置文件中的k/v保存到運行環境中,結合@value使用,或使用ConfigurableEnvironment獲取
  • @Profile:結合@Bean使用,默認爲default環境,能夠經過命令行參數來切換環境
  • 自定義組件使用Spring容器底層的組件:須要讓自定義組件實現xxxAware,(例如:ApplicationContextAware),spring在建立對象的時候,會幫咱們自動注入。spring經過BeanPostProcessor機制來實現XXXXAware的自動注入。
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);
            }
        }
    }
  • @Autowried 裝配優先級以下:spring

    1. 使用按照類型去容器中找對應的組件
    2. 按照屬性名稱去做爲組件id去找對應的組件
  • @Qualifier:指定默認的組件,結合@Autowried使用
    --標註在構造器:spring建立對象調用構造器建立對象
    --標註在方法上:
  • @Primary:spring自動裝配的時候,默認首先bean,配合@Bean使用
  • @Resource(JSR250):jsr規範:按照組件名稱進行裝配
  • @Inject(JSR330):jsr規範和@Autowired功能一致,不支持require=false;

Bean生命週期:

初始化和銷燬數組

  1. 經過@Bean 指定init-method和destroy-method
  2. 實現InitializingBean定義初始化邏輯,實現DisposableBean定義銷燬方法
  3. 實現BeanPostProcessor接口的後置攔截器放入容器中,能夠攔截bean初始化,並能夠在被攔截的Bean的初始化先後進行一些處理工做。

spring底層經常使用的BeanPostProcessor:mybatis

* BeanValidationPostProcessor用來實現數據校驗
* AutowireAnnotationBeanPostProcessor,@Autowire實現
* ApplicationContextProcessor實現XXXAware的自動注入。

執行時機app

doCreateBean
-populateBean():給bean的各類屬性賦值
-initializeBean():初始化bean
-處理Aware方法
-applyBeanPostProcessorsBeforeInitialization:後置處理器的實例化前攔截
-invokeInitMethods:執行@Bean指定的initMethod
-applyBeanPostProcessorsAfterInitialization:後置處理器的實例化後攔截

SpringAOP實現原理

使用步驟異步

  1. @EnableAspectJAutoProxy 開啓基於註解的aop模式
  2. @Aspect:定義切面類,切面類裏定義通知
  3. @PointCut 切入點,能夠寫切入點表達式,指定在哪一個方法切入
  4. 通知方法函數

    • @Before(前置通知)
    • @After(後置通知)
    • @AfterReturning(返回通知)
    • @AfterTrowing(異常通知)@Around(環繞通知)
  5. JoinPoint:鏈接點,是一個類,配合通知使用,用於獲取切入的點的信息

SpringAop原理post

  1. @EnableAspectJAutoProxyui

    • @EnableAspectJAutoProxy 經過@Import(AspectJAutoProxyRegistrar.class)給spring容器中導入了一個AnnotationAwareAspectJAutoProxyCreator。
    • AnnotationAwareAspectJAutoProxyCreator實現了InstantiationAwareBeanPostProcessor,InstantiationAwareBeanPostProcessor是一個BeanPostProcessor。它能夠攔截spring的Bean初始化(Initialization)先後和實例化(Initialization)先後。
  2. AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation(bean實例化前):會經過調用isInfrastructureClass(beanClass)來判斷 被攔截的類是不是基礎類型的Advice、PointCut、Advisor、AopInfrastructureBean,或者是不是切面(@Aspect),如果則放入adviseBean集合。這裏主要是用來處理咱們的切面類。
  3. AnnotationAwareAspectJAutoProxyCreator的BeanPostProcessorsAfterInitialization(bean初始化後):this

    1. 首先找到被攔截的Bean的匹配的加強器(通知方法),這裏有切入點表達式匹配的邏輯
    2. 將加強器保存到proxyFactory中,
    3. 根據被攔截的Bean是否實現了接口,spring自動決定使用JdkDynamicAopProxy仍是ObjenesisCglibAopProxy
    4. 最後返回被攔截的Bean的代理對象,註冊到spring容器中
  4. 代理Bean的目標方法執行過程:CglibAopProxy.intercept();

    1. 保存全部的加強器,並處理轉換爲一個攔截器鏈
    2. 若是沒有攔截器鏈,就直接執行目標方法
    3. 若是有攔截器鏈,就將目標方法,攔截器鏈等信息傳入並建立CglibMethodInvocation對象,並調用proceed()方法獲取返回值。proceed方法內部會依次執行攔截器鏈。

spring 聲明式事務

基本步驟

  1. 配置數據源:DataSource
  2. 配置事務管理器來控制事務:PlatformTransactionManager
  3. @EnableTransactionManagement開啓基於註解的事務管理功能
  4. 給方法上面標註@Transactional標識當前方法是一個事務方法

聲明式事務實現原理

  1. @EnableTransactionManagement利用TransactionManagementConfigurationSelector給spring容器中導入兩個組件:AutoProxyRegistrar和ProxyTransactionManagementConfiguration
  2. AutoProxyRegistrar給spring容器中註冊一個InfrastructureAdvisorAutoProxyCreator,InfrastructureAdvisorAutoProxyCreator實現了InstantiationAwareBeanPostProcessor,InstantiationAwareBeanPostProcessor是一個BeanPostProcessor。它能夠攔截spring的Bean初始化(Initialization)先後和實例化(Initialization)先後。利用後置處理器機制在被攔截的bean建立之後包裝該bean並返回一個代理對象代理對象執行方法利用攔截器鏈進行調用(同springAop的原理)
  3. ProxyTransactionManagementConfiguration:是一個spring的配置類,它爲spring容器註冊了一個BeanFactoryTransactionAttributeSourceAdvisor,是一個事務事務加強器。它有兩個重要的字段:AnnotationTransactionAttributeSource和TransactionInterceptor。

    1. AnnotationTransactionAttributeSource:用於解析事務註解的相關信息
    2. TransactionInterceptor:事務攔截器,在事務方法執行時,都會調用TransactionInterceptor的invoke->invokeWithinTransaction方法,這裏面經過配置的PlatformTransactionManager控制着事務的提交和回滾。

Spring 擴展(鉤子)

  1. BeanFactoryPostProcessor:beanFactory後置處理器,的攔截時機:全部Bean的定義信息已經加載到容器,但尚未被實例化。能夠對beanFactory進行一些操做。
  2. BeanPostProcessor:bean後置處理器,攔截時機:bean建立對象初始化先後進行攔截工做。能夠對每個Bean進行一些操做。
  3. BeanDefinitionRegistryPostProcessor:是BeanFactoryPostProcessor的子接口,攔截時機:全部Bean的定義信息已經加載到容器,但尚未被實例化,能夠對每個Bean的BeanDefinition進行一些操做。
  4. ApplicationListener,自定義ApplicationListener實現類並加入到容器中,能夠監聽spring容器中發佈的事件。spring在建立容器的時候(finishRefresh()方法)會發布ContextRefreshedEvent事件,關閉的時候(doClose())會發布ContextClosedEvent事件。也能夠經過spring容器的publishEvent發佈本身的事件。

    1. 事件發佈流程:publishEvent方法

      1. 獲取事件的多播器,getApplicationEventMulticaster()。
      2. 調用multicastEvent(applicationEvent, eventType)派發事件。獲取到全部的ApplicationListener,即getApplicationListeners(),而後同步或者異步的方式執行監聽器的onApplicationEvent。
    2. 事件的多播器的初始化中(initApplicationEventMulticaster()),若是容器中沒有配置applicationEventMulticaster,就使用SimpleApplicationEventMulticaster。而後獲取全部的監聽器,並把它們註冊到SimpleApplicationEventMulticaster中。
  5. @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的過程:

  1. 先從主從中心取出全部的BeanDefinition。依次判斷,若一個BeanDefinition是被@Configuration標註的,spring將其標記爲FullMode,不然若一個BeanDefinition沒有被@Configuration標註,但有被@Bean標註的方法,spring將其標記爲LightMode。篩選出全部候選配置BeanDefinition(FullMode和LightMode)
  2. 建立一個ConfigurationClassParser,調用parse方法解析每個配置類。

    1. 解析@PropertySources,將解析結果設置到Environment
    2. 利用ComponentScanAnnotationParser,將@ComponentScans標籤解析成BeanDefinitionHolder。再迭代解析BeanDefinitionHolder
    3. 解析@Import,@ImportResource
    4. 將@Bean解析爲MethodMetadata,將結果保存到ConfigurationClass中。最終ConfigurationClass會被保存到ConfigurationClassParser的configurationClasses中。
  3. 調用ConfigurationClassParser的loadBeanDefinitions方法,加載解析結果到註冊中。

    1. 從利用ComponentScanAnnotationParser的configurationClasses獲取全部的ConfigurationClass,依次調用loadBeanDefinitionsForConfigurationClass方法。
    2. loadBeanDefinitionsForConfigurationClass會將每個BeanMethod轉爲ConfigurationClassBeanDefinition,最後將其添加到spring的註冊中心。

beanFactory.getBean方法執行的過程

  1. 首先將方法傳入的beanName進行轉換:先去除FactoryBean前綴(&符)若是傳遞的beanName是別名,則經過別名找到bean的原始名稱。
  2. 根據名稱先從singletonObjects(一個Map類型的容)獲取bean實例。若是能獲取到就先判斷該bean實例是否實現了FactoryBean,若是是FactoryBean類型的bean實例,就經過FactoryBean獲取Bean。而後直接返回該bean實例。getBean方法結束。
  3. 若是從singletonObjects沒有獲取到bean實例就開始建立Bean的過程。

    1. 首先標記該Bean處於建立狀態。
    2. 根據Bean的名稱找到BeanDefinition。查看該Bean是否有前置依賴的Bean。如有則先建立該Bean前置依賴的Bean。
    3. spring調用AbstractAutowireCapableBeanFactory的createBean方法並傳入BeanDefinition開始建立對象。先調用resolveBeforeInstantiation給BeanPostProcessor一個機會去返回一個代理對象去替代目標Bean的實例。
    4. 若是BeanPostProcessor沒有返回Bean的代理就經過doCreateBean方法建立對象。

      1. 首先肯定Bean的構造函數,若是有有參構造器,先自動裝配有參構造器,默認使用無參數構造器。
      2. 選擇一個實例化策略去實例化bean。默認使用CglibSubclassingInstantiationStrategy。該策略模式中,首先判斷bean是否有方法被覆蓋,若是沒有則直接經過反射的方式來建立,若是有的話則經過CGLIB來實例化bean對象. 把建立好的bean對象包裹在BeanWrapper裏。
      3. 調用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition
      4. 判斷容器是否容許循環依賴,若是容許循環依賴,就建立一個ObjectFactory類並實現ObjectFactory接口的惟一的一個方法getObject()用於返回Bean。而後將該ObjectFactory添加到singletonFactories中。
      5. 調用populateBean爲bean實例賦值。在賦值以前執行InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation和postProcessPropertyValues方法。
      6. 調用initializeBean初始化bean。若是Bean實現了XXXAware,就先處理對應的Aware方法。而後調用beanProcessor的postProcessBeforeInitialization方法。再以反射的方式調用指定的bean指定的init方法。最後調用beanProcessor的postProcessAfterInitialization方法。
      7. 調用registerDisposableBeanIfNecessary,將該bean保存在一個以beanName爲key,以包裝了bean引用的DisposableBeanAdapter,爲value的map中,在spring容器關閉時,遍歷這個map來獲取須要調用bean來依次調用Bean的destroyMethod指定的方法。
    5. 將新建立出來的Bean保存到singletonObjects中

spring原理補充

spring解決循環依賴

以類A,B互相依賴注入爲例

  1. 根據類A的名稱先從singletonObjects獲取Bean實例,發現獲取不到,就經過doGetBean方法開始建立Bean的流程。
  2. 根據A的名稱找到對應的BeanDefinition,經過doCreateBean()方法建立對象,先肯定類A的構造函數,而後選擇一個實例化策略去實例化類A。
  3. 判斷容器是否容許循環依賴,若是容許循環依賴,就建立一個ObjectFactory類並實現ObjectFactory接口的惟一的一個方法getObject()用於返回類A。而後將該ObjectFactory添加到singletonFactories中。
  4. 調用populateBean()爲類A進行屬性賦值,發現須要依賴類B,此時類B還沒有建立,啓動建立類B的流程。

    1. 根據類B的名稱先從singletonObjects獲取Bean實例,發現獲取不到,就開始經過doGetBean方法開始建立Bean的流程
    2. 找到類B對應的BeanDefinition,確認B的構造函數,而後實例化B。
    3. 判斷容器是否容許循環依賴,建立一個ObjectFactory並實現getObject()方法,用於返回類B,並添加到singletonFactories中。
    4. 調用populateBean()爲類B進行屬性賦值,發現須要依賴類A,調用getSingleton方法獲取A:A如今已存在於singletonFactories中,getSingleton將A從singletonFactories方法中移除並放入earlySingletonObjects中。
    5. 調用getSingleton()方法獲取B:getSingleton將A從singletonFactories方法中移除並放入earlySingletonObjects中。
    6. 調用initializeBean初始化bean,最後將新建立出來的類B保存到singletonObjects中
  5. 調用getSingleton()方法獲取A,這時A已在earlySingletonObjects中了,就直接返回A
  6. 調用initializeBean初始化bean,最後將新建立出來的類B保存到singletonObjects中。

@Autowire 實現原理

上面介紹beanFactory.getBean方法執行的過程中提到:populateBean爲bean實例賦值。在賦值以前執行InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation和postProcessPropertyValues方法。@Autowire由AutowiredAnnotationBeanPostProcessor完成,它實現了InstantiationAwareBeanPostProcessor。
AutowiredAnnotationBeanPostProcessor執行過程:

  1. postProcessAfterInstantiation方法執行,直接return null。
  2. postProcessPropertyValues方法執行,主要邏輯在此處理。待補充。。。。。
相關文章
相關標籤/搜索