Spring 源碼解析(一)

Spring 源碼解析

  • 第一章為源碼解析。
  • 第二章為實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 IOC 容器蚊荣。
  • 第三章進(jìn)階 Spring 插件開發(fā)。

概念

Spring 源碼的核心組件:

  • IOC 容器負(fù)責(zé)實(shí)例化,定位,配置應(yīng)用程序中的對(duì)象及建立這些對(duì)象間的依賴油坝。
  • AOP 面向切面編程,通過預(yù)編譯方式和運(yùn)行期間動(dòng)態(tài)代理實(shí)現(xiàn)功能的統(tǒng)一維護(hù)的一種技術(shù)刨裆。

IOC 容器可以理解為一個(gè) Map澈圈,key 就是我們平常使用 Spring 框架時(shí)寫的 Bean Id,value 就是對(duì)應(yīng)類的實(shí)例化對(duì)象帆啃。

幾個(gè)重要的類

在開始分析源碼之前瞬女,我們先試著了解幾個(gè)概念,這幾個(gè)類對(duì)于我們理解源碼有著很大的幫助努潘,方便對(duì)整個(gè) Spring 源碼進(jìn)行分析诽偷。

  1. ApplicationContext,BeanFactory
    提到 Spring 就一直說容器疯坤,這個(gè)容器我們上面也給出了一個(gè)直觀的解釋报慕,可以理解為一個(gè) Map,用來存儲(chǔ)實(shí)例化的的對(duì)象压怠,需要的時(shí)候就從容器里面取就可以了眠冈。那么在代碼中的具體實(shí)現(xiàn)是什么那?

    大家最為熟悉的實(shí)現(xiàn)可能就是 ApplicationContext菌瘫,它就是一個(gè)容器蜗顽,而它實(shí)現(xiàn)了 BeanFactory 接口,可以說 BeanFactory 就是最基礎(chǔ)的容器雨让,ApplicationContext 相當(dāng)于在 BeanFactory 接口增加了一些功能雇盖,它們都可以稱為容器。

    先來看看 BeanFactory 的代碼:

    public interface BeanFactory {
     String FACTORY_BEAN_PREFIX = "&";
    
     Object getBean(String var1) throws BeansException;
    
     <T> T getBean(String var1, @Nullable Class<T> var2) throws BeansException;
    
     Object getBean(String var1, Object... var2) throws BeansException;
    
     <T> T getBean(Class<T> var1) throws BeansException;
    
     <T> T getBean(Class<T> var1, Object... var2) throws BeansException;
    
     boolean containsBean(String var1);
    
     boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
    
     boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
    
     boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
    
     boolean isTypeMatch(String var1, @Nullable Class<?> var2) throws NoSuchBeanDefinitionException;
    
     @Nullable
     Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
    
     String[] getAliases(String var1);
        
    }
    

    整個(gè)接口定義的抽象方法其實(shí)非常簡(jiǎn)單和直接,主要就是各種個(gè)樣的 getBean 方法和一些判斷是否是單例或者原型的方法栖忠。

    再來看 ApplicationContext崔挖。

    public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
     @Nullable
     String getId();
    
     String getApplicationName();
    
     String getDisplayName();
    
     long getStartupDate();
    
     @Nullable
     ApplicationContext getParent();
    
     AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
    }
    

    不僅僅實(shí)現(xiàn)了 BeanFactory 接口贸街,而且實(shí)現(xiàn)了事件派發(fā)器,資源解析器以及環(huán)境參數(shù)相關(guān)的接口狸相,比 BeanFactory 多了許多功能匾浪。

    下面來看看常用的容器,也就是上面接口的實(shí)現(xiàn)類卷哩。

    • AnnotationConfigApplicationContext
      基于 @Configuration 注解配置類解析的容器蛋辈。
    • ClassPathXmlApplicationContext
      基于類路徑下 xml 文件配置解析的容器,如果用 xml 方式配置 Spring 框架,這個(gè)容器一定使用的非常多。
    • FileSystemXmlApplicationContext
      基于文件系統(tǒng)里的 xml 文件配置解析的容器舔示。
    • GenericApplicationContext
      不太常用的 ApplicationContext,比上面兩個(gè)更加靈活逞频,可以讀取任意配置方式的 Bean。
  2. BeanDefinition
    BeanDefinition 按照字面意思理解就是 Bean 的定義信息栋齿,我們從接口的定義來看看這個(gè)類到底保存了什么信息苗胀。

    public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
     String SCOPE_SINGLETON = "singleton";
     String SCOPE_PROTOTYPE = "prototype";
     int ROLE_APPLICATION = 0;
     int ROLE_SUPPORT = 1;
     int ROLE_INFRASTRUCTURE = 2;
    
     void setParentName(@Nullable String var1);
    
     @Nullable
     String getParentName();
    
     void setBeanClassName(@Nullable String var1);
    
     @Nullable
     String getBeanClassName();
    
     void setScope(@Nullable String var1);
    
     @Nullable
     String getScope();
    
     void setLazyInit(boolean var1);
    
     boolean isLazyInit();
    
     void setDependsOn(@Nullable String... var1);
    
     @Nullable
     String[] getDependsOn();
    
     void setAutowireCandidate(boolean var1);
    
     boolean isAutowireCandidate();
    
     void setPrimary(boolean var1);
    
     boolean isPrimary();
    
     void setFactoryBeanName(@Nullable String var1);
    
     @Nullable
     String getFactoryBeanName();
    
     void setFactoryMethodName(@Nullable String var1);
    
     @Nullable
     String getFactoryMethodName();
    
     ConstructorArgumentValues getConstructorArgumentValues();
    
     default boolean hasConstructorArgumentValues() {
         return !this.getConstructorArgumentValues().isEmpty();
     }
    
     MutablePropertyValues getPropertyValues();
    
     default boolean hasPropertyValues() {
         return !this.getPropertyValues().isEmpty();
     }
    
     boolean isSingleton();
    
     boolean isPrototype();
    
     boolean isAbstract();
    
     int getRole();
    
     @Nullable
     String getDescription();
    
     @Nullable
     String getResourceDescription();
    
     @Nullable
     BeanDefinition getOriginatingBeanDefinition();
    }
    
    

    從代碼里看,BeanDefintion 里面保存了 Bean 的 Class 類名稱瓦堵,作用域【單例或者原型】基协,構(gòu)造函數(shù)的參數(shù),屬性等等菇用,這些信息也說明這個(gè)類是 Spring 用來構(gòu)建 Bean 的主要的類澜驮。

    這個(gè)接口的主要實(shí)現(xiàn)類有 RootBeanDefinition,ChildBeanDefinition惋鸥,GenericBeanDefinition等等杂穷。其中 RootBeanDefinition 最為常用,相當(dāng)于 xml 文件中的 <bean> 標(biāo)簽卦绣,在 xml 中可以配置 parent 屬性耐量,這里的父就是 RootBeanDefinition,子就是 ChildBeanDefinition滤港。

  3. BeanDefinitionRegistry
    既然有了材料 BeanDefinition廊蜒,下面一定需要一個(gè)操作它的類,BeanDefinitionRegistry 就是一個(gè)用來幫我們操作 BeanDefinition 的接口蜗搔,它的里面有許多操作 BeanDefinition 的方法劲藐,包括通過 BeanDefinition 注冊(cè) Bean 等等八堡。

    public interface BeanDefinitionRegistry extends AliasRegistry {
     void registerBeanDefinition(String var1, BeanDefinition var2) throws BeanDefinitionStoreException;
    
     void removeBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
    
     BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;
    
     boolean containsBeanDefinition(String var1);
    
     String[] getBeanDefinitionNames();
    
     int getBeanDefinitionCount();
    
     boolean isBeanNameInUse(String var1);
    }
    

    我們可以通過 registerBeanDefinition 方法將一個(gè) Bean 注冊(cè)到容器中樟凄。調(diào)用 BeanDefinitionRegistry.registerBeanDefinition 手工進(jìn)行注冊(cè)。

    BeanDefinitionRegistry registry = context.getRegistry();
    boolean definition = registry.containsBeanDefinition("person");
    
  4. BeanPostProcessor
    BeanPostProcessor兄渺,bean 的后置處理器缝龄,在 bean 初始化前后進(jìn)行一些處理工作。postProcessBeforeInitialization:在初始化之前
    工作。postPorcessAfterInitialization:在初始化之后工作叔壤。

    
    public interface BeanPostProcessor {
     @Nullable
     default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
         return bean;
     }
    
     @Nullable
     default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
         return bean;
     }
    }
    

    由此衍生出來的后置處理器非常多瞎饲,處理時(shí)機(jī)也不一樣,我們會(huì)在后面的源碼分析對(duì)這些后置處理器的實(shí)現(xiàn)原理和操作時(shí)機(jī)進(jìn)行一個(gè)總結(jié)炼绘。
    Spring 底層對(duì) BeanPostProcessor 的使用:bean 賦值嗅战,注入其他組件,@Autowired俺亮,聲明周期注解功能驮捍,@Async等等。

  5. ApplicationContextAware
    自定義組件想要使用 Spring 容器底層的一些組件(ApplicationContext脚曾,BeanFactory东且,xxx)等等,需要自定義組件實(shí)現(xiàn) xxxAware 接口本讥。在創(chuàng)建對(duì)象的時(shí)候珊泳,會(huì)調(diào)用接口規(guī)定的方法注入相關(guān)組件。ApplicationContextAware 會(huì)將 IOC 容器傳入到組件中拷沸,BeanNameAware 會(huì)講當(dāng)前實(shí)例在 IOC 容器中 Bean 的名字傳入到實(shí)例中色查。這些 Aware 會(huì)有對(duì)應(yīng)的 AwareProcessor 來進(jìn)行邏輯處理。

    public interface ApplicationContextAware extends Aware {
     void setApplicationContext(ApplicationContext var1) throws BeansException;
    }
    

    如果想往組件中注入容器可以實(shí)現(xiàn) ApplicationContextAware 接口撞芍,然后通過 setApplicationContext 保存起來综慎。 我們對(duì) Spring 功能進(jìn)行擴(kuò)展時(shí)常常喲昂到這些 Aware。

  6. ApplicationListener 與 ApplicationEventMulticaster
    這兩個(gè)組件是 Spring 事件驅(qū)動(dòng)模型用到的組件勤庐,ApplicationListener:事件監(jiān)聽示惊。ApplicationEventMulticaster:事件派發(fā)。

Bean 的生命周期

Bean 的聲明周期指的是 Bean 的創(chuàng)建-->初始化-->銷毀的過程愉镰,Spring 把這個(gè)過程全部交給容器來管理米罚。我們可以自定義初始化和銷毀方法,容器在 Bean 進(jìn)行到當(dāng)前生命周期的時(shí)候來調(diào)用我們自定一的初始化和銷毀方法丈探。

構(gòu)造(對(duì)象創(chuàng)建)
單實(shí)例:在容器啟動(dòng)的時(shí)候創(chuàng)建對(duì)象录择。
多實(shí)例:在每次獲取的時(shí)候創(chuàng)建對(duì)象,調(diào)用 getBean 方法時(shí)碗降。

初始化
對(duì)象創(chuàng)建完成隘竭,并賦值好,調(diào)用初始化方法

銷毀
單實(shí)例:容器關(guān)閉的時(shí)候讼渊。
多實(shí)例:容器會(huì)創(chuàng)建 Bean动看, 但不會(huì)管理 Bean,容器不會(huì)調(diào)用銷毀方法爪幻。

Bean 的生命周期要比上面寫的更加復(fù)雜菱皆,我們?cè)诜治鐾暝创a后會(huì)對(duì)這部分進(jìn)行一個(gè)總結(jié)须误。

幾個(gè)重要的注解

@Import,快速給容器中導(dǎo)入一個(gè)組件仇轻,@Import(Color.class) 相當(dāng)于一個(gè)無參構(gòu)造函數(shù)京痢。id 默認(rèn)是全類名。

@Conditional 滿足一定條件才給容器中注冊(cè)bean篷店,這個(gè)可以用來讓兩個(gè)bean形成依賴祭椰,可以用在方法上,也可以用在類上疲陕。這個(gè)注解在 SpringBoot 用的非常多吭产。

最后說說 @Autowired 和 @Resource 的區(qū)別:
@Autowired 自動(dòng)注入默認(rèn)按照 type 注入,即按照 .class 查找鸭轮。如果找到多個(gè)相同類型的組件臣淤,在將屬性的名稱作為組件的 id 去容器中查找。使用 @Qualifier("bookDao") 與 @Autowired 組合可以明確指定需要裝配的 Bean窃爷,通過 id邑蒋。
@Autowired(require=false) 有就裝配,沒有就變?yōu)?null按厘。

Spring 還支持 JSR250 和 JSR330 里的 @Resource 和 @Inject 注解医吊。Java 規(guī)范的注解。@Resource 和 @Autowired 一樣實(shí)現(xiàn)自動(dòng)裝配逮京,默認(rèn)按照屬性名稱進(jìn)行自動(dòng)裝配卿堂。不支持 @Primary,也不支持 @Autowired(require=false)懒棉。
@Inject 需要額外導(dǎo)入包草描,功能和 @Autowired 一樣,不支持 require=false策严;
@Autowired 可以標(biāo)注在構(gòu)造器穗慕、參數(shù)、方法妻导、屬性上逛绵。

提出問題

有了一些概念后,我們心里一定會(huì)有一些問題倔韭,同時(shí)帶著問題去看源碼也有助于我們更加快速地切入到 Spring 得核心术浪,不墨跡,直給寿酌。

  1. 容器時(shí)怎么創(chuàng)建得胰苏,創(chuàng)建時(shí)都要做哪些工作。
  2. Spring 為什么要用 BeanDefintion 去構(gòu)造 Bean份名。
  3. Spring 用 BeanDefintion 去構(gòu)建 Bean 得流程是什么碟联?
  4. Spring AOP 在 Spring 框架得基礎(chǔ)上做了什么妓美?

下面我們帶著問題去看看源碼僵腺。

容器創(chuàng)建和初始化過程

還是從下面這段代碼開始

AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Config.class);

new 容器的過程到底執(zhí)行了什么操作那鲤孵?前兩步是預(yù)處理和配置類的解析工作,我們直接看 refresh 方法辰如,這個(gè)方法就是容器的創(chuàng)建和刷新以及 Bean 初始化的核心方法普监。

public AnnotationConfigApplicationContext(Class... annotatedClasses) {
  this();
  this.register(annotatedClasses);
  this.refresh();
}

refresh() 核心方法:

public void refresh() throws BeansException, IllegalStateException {
  synchronized(this.startupShutdownMonitor) {
    this.prepareRefresh();
    ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
    this.prepareBeanFactory(beanFactory);

    try {
      this.postProcessBeanFactory(beanFactory);
      this.invokeBeanFactoryPostProcessors(beanFactory);
      this.registerBeanPostProcessors(beanFactory);
      this.initMessageSource();
      this.initApplicationEventMulticaster();
      this.onRefresh();
      this.registerListeners();
      this.finishBeanFactoryInitialization(beanFactory);
      this.finishRefresh();
    } catch (BeansException var9) {
      if (this.logger.isWarnEnabled()) {
        this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
      }

      this.destroyBeans();
      this.cancelRefresh(var9);
      throw var9;
    } finally {
      this.resetCommonCaches();
    }

  }
}
  1. prepareRefresh() 刷新前的預(yù)處理
  • initPropertySources,字面上理解就是初始化一些屬性琉兜,但是方法體是空的凯正,留給子類去實(shí)現(xiàn)。子類可以自定義個(gè)性化屬性設(shè)置方法豌蟋。
  • getEnvironment().validateRequiredProperties()廊散,屬性校驗(yàn)。
  • earlyApplicationEvents梧疲,用來保存容器中的一些早期的事件允睹。等事件派發(fā)器初始化好了之后再把它們派發(fā)出去。
  1. obtainFreshBeanFactory() 獲取 Bean 工廠幌氮。
  • refreshBeanFactory()缭受,刷新【創(chuàng)建】 BeanFactory。

    在 GenericApplicationContext 里無參構(gòu)造器創(chuàng)建一個(gè) BeanFactory 對(duì)象该互。

    this.beanFactory = new DefaultListableBeanFactory();
    

    設(shè)置一個(gè) Id米者。

  • getBeanFactory(),返回剛才 GenericApplicationContext 創(chuàng)建的 BeanFactory 對(duì)象宇智。剛創(chuàng)建蔓搞,里面都是默認(rèn)的配置。

  • 將創(chuàng)建的 BeanFactory【DefaultListableBeanFactory】返回随橘。

  1. prepareBeanFactory()败明,BeanFactory 的預(yù)準(zhǔn)備工作,BeanFactory 進(jìn)行一些設(shè)置太防。
  • 設(shè)置 BeanFactory 的類加載器妻顶、支持表達(dá)式解析器。蜒车。讳嘱。

  • 添加 部分的BeanPostProcessor【ApplicationContextAwareProcessor】

  • 設(shè)置忽略自動(dòng)裝配的接口,EnvironmentAware酿愧、EmbeddedValueResolverAware沥潭。。嬉挡。

  • 注冊(cè)可以解析的自動(dòng)裝配钝鸽,我們可以在任何組件中自動(dòng)注入汇恤,ResourceLoader,BeanFactory拔恰,ApplicationContext因谎。

  • 添加 BeanPostProcessor【ApplicationListenerDetector】。

  • 添加編譯時(shí)的 AspectJ颜懊。

  • 給 BeanFactory 中注冊(cè)一些能用的組件财岔。

    environment

    systemProperties

    systemEnvironment

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  beanFactory.setBeanClassLoader(this.getClassLoader());
  beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
  beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
  beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
  beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
  beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
  beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
  beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
  beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
  beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
  beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
  beanFactory.registerResolvableDependency(ResourceLoader.class, this);
  beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
  beanFactory.registerResolvableDependency(ApplicationContext.class, this);
  beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
  if (beanFactory.containsBean("loadTimeWeaver")) {
    beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
    beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
  }

  if (!beanFactory.containsLocalBean("environment")) {
    beanFactory.registerSingleton("environment", this.getEnvironment());
  }

  if (!beanFactory.containsLocalBean("systemProperties")) {
    beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
  }

  if (!beanFactory.containsLocalBean("systemEnvironment")) {
    beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
  }

}
  1. postProcessBeanFactory,BeanFactory 準(zhǔn)備工作完成后進(jìn)行的后置處理工作河爹,子類通過重寫這個(gè)方法來在 BeanFactory 創(chuàng)建并預(yù)備完成以后做進(jìn)一步的設(shè)置匠璧。

=============================以上是 BeanFactory 創(chuàng)建及準(zhǔn)備================================

  1. invokeBeanFactoryPostProcessors(beanFactory),執(zhí)行 BeanFactoryPostProcessor咸这。

BeanFactoryProcessor:BeanFactory 的后置處理器夷恍,在 BeanFactory 標(biāo)準(zhǔn)初始化執(zhí)行的 Processor,標(biāo)準(zhǔn)初始化就是以上四部媳维。

兩個(gè)主要接口酿雪,BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor(可以用這個(gè)來注冊(cè)一些新的組件 )侨艾。

執(zhí)行 BeanPostProcessor 的方法:

先執(zhí)行 BeanDefintionRegistryPostProcessor

  • 獲取所有的 BeanDefinitionRegistryPostProcessor执虹。

  • 對(duì)于實(shí)現(xiàn)了 PriorityOrdered 優(yōu)先級(jí)接口的 BeanDefinitionRegistryPostProcessor

    postProcessor.postProcessBeanDefinitionRegistry(registry)

  • 對(duì)于實(shí)現(xiàn)了 Ordered 順序接口的 BeanDefinitionRegistryPostProcessor

    postProcessor.postProcessBeanDefinitionRegistry(registry)

  • 最后執(zhí)行沒有實(shí)現(xiàn)任何優(yōu)先級(jí)或者是順序接口的 BeanDefinitionRegistryPostProcessor

    postProcessor.postProcessBeanDefinitionRegistry(registry)

在執(zhí)行 BeanFactoryPostProcessor 的方法

  • 流程和 BeanDefinitionRegistryPostProcessor 一模一樣。
  1. registerBeanPostProcessors唠梨,注冊(cè) BeanPostProcessor袋励,Bean 的后置處理器【攔截 Bean 的創(chuàng)建過程】。

不同接口類型的 BeanPostProcessor当叭,在 Bean 創(chuàng)建前后的執(zhí)行時(shí)機(jī)是不一樣的茬故。

BeanPostProcessor

DestructionAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor

SmartInstantiationAwareBeanPostProcessor

MergedBeanDefinitionPostProcessor【internalPostProcessors】

  • 獲取所有的 BeanPostProcessor,后置處理器都默認(rèn)可以有 PriorityOrdered蚁鳖,Ordered 來指定優(yōu)先級(jí)磺芭。

  • 先注冊(cè) PriorityOrdered 優(yōu)先級(jí)接口的 BeanPostProcessor,把每一個(gè) BeanPostProcessor 添加到 BeanFactory 中醉箕。

    beanFactory.addBeanPostProcessor(postProcessor)
    
  • 再注冊(cè) Ordered 接口的钾腺。

  • 最后注冊(cè)沒有實(shí)現(xiàn)任何優(yōu)先級(jí)接口的。

  • 最終注冊(cè)讥裤,MergedBeanDefinitionPostProcessor放棒。

  • 注冊(cè)一個(gè) ApplicationListenerDetector,來在 Bean 創(chuàng)建完成后檢查是否是 ApplicationListener己英,如果是

    applicationContext.addApplicationListener((ApplicationListener<?>) bean);
    
  1. initMessageSource间螟,初始化 MessageSource 組件,做國(guó)際化消息,消息綁定厢破,消息解析荣瑟。
  • 獲取 BeanFactory。

  • 判斷容器有沒有 id 為 messageSource 的摩泪,類型是 MessageSource 的組件

    如果有賦值給 messageSource 屬性笆焰,如果沒有自己創(chuàng)建一個(gè) DelegatingMessageSource。

    MessageSource 取出國(guó)際化配置文件中的某個(gè) key 值加勤,能按照區(qū)域信息獲取仙辟。

  • 把創(chuàng)建好的 MessageSource 注冊(cè)到容器中同波,以后獲取國(guó)際化配置文件的值的時(shí)候鳄梅,可以自動(dòng)注入 MessageSource,調(diào)用 getMessage 方法就可以獲取到了未檩。

    beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource)
    
  1. initApplicationEventMulticaster戴尸,初始化事件派發(fā)器。
  • 獲取 BeanFactory冤狡。
  • 從 BeanFactory 中獲取 ID 為 applicationEventMulticaster孙蒙,類型為 ApplicationEventMulticaster 的派發(fā)器。
  • 如果上一步?jīng)]有配置事件派發(fā)器悲雳,就創(chuàng)建一個(gè) SimpleApplicationEventMulticaster挎峦,為我們派發(fā)事件。
  • 將創(chuàng)建的 ApplicationEventMulticaster 添加到 BeanFactory 中合瓢,以后其他組件自動(dòng)注入即可坦胶。
  1. onRefresh,留給子容器(子類)晴楔,重寫 onRefresh 方法顿苇,在容器刷新時(shí)可以再自定義邏輯。

  2. registerListeners税弃,給容器中把項(xiàng)目里的 ApplicationListener 注冊(cè)進(jìn)來纪岁。

  • 從容器中拿到所有的 ApplicationListener 組件,將每個(gè)監(jiān)聽器添加到事件派發(fā)器中则果。

    getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName)
    
  • 派發(fā)之前步驟產(chǎn)生的事件幔翰,派發(fā)器沒初始化之前的。

  1. finishBeanFactoryInitialization西壮,初始化所有剩下的單實(shí)例 Bean遗增。
//初始化所有剩下的單實(shí)例 bean。
beanFactory.preInstantiateSingletons();
  • 獲取容器中的所有 BeanDefinitions茸时,依次進(jìn)行初始化和創(chuàng)建對(duì)象贡定。

  • 如果 Bean 不是抽象的,是單實(shí)例可都,不是懶加載的缓待,就開始創(chuàng)建單例 Bean蚓耽。

    判斷是否是 FactoryBean,即是否實(shí)現(xiàn)了 FactoryBean 接口的 Bean旋炒,如果是就用工廠方法創(chuàng)建對(duì)象步悠。

    如果不是工廠 Bean,利用 getBean(beanName) 創(chuàng)建對(duì)象瘫镇。

    • getBean(beanName)鼎兽,就是自己寫測(cè)試類的那個(gè) getBean。

    • 調(diào)用 doGetBean(name,null,null,false)铣除。

    • 先獲取緩存中保存的單實(shí)例 Bean谚咬,如果能獲取到說明這個(gè) Bean 之前被創(chuàng)建過了(所有創(chuàng)建過的單實(shí)例 Bean 都會(huì)被緩存起來)。

      //保存單實(shí)例 Bean 的
      private final Map<String,Object> singletonObjects = new ConcurrentHashMap<String,Object>(256);
      
- 緩存中獲取不到尚粘,開始 Bean 的創(chuàng)建對(duì)象流程择卦。

- 標(biāo)記當(dāng)前 Bean 已經(jīng)被創(chuàng)建。

- 獲取 Bean 的定義信息郎嫁。

- 獲取當(dāng)前 Bean 所依賴的其他 Bean秉继,如果有就按照 getBean() 把依賴的 Bean 先創(chuàng)建出來。

- 啟動(dòng)單實(shí)例 Bean 的創(chuàng)建流程泽铛。

  ```java
  createBean(beanName,mbd,args);
  
  //讓 BeanPostProcessor 攔截返回對(duì)象尚辑。正常的 BeanPostProcessor 是對(duì)象創(chuàng)建完成初始化之前執(zhí)行的,而這個(gè) BeanPostProcessor 要在 Bean 創(chuàng)建之前執(zhí)行
  
  //InstantiationAwareBeanPostProcessor 提前執(zhí)行
  //觸發(fā) postProcessBeforeInstantiation 方法
  //如果上一步有返回值盔腔,在觸發(fā) postProcessAfterInitialization 方法
  Object bean = resolveBeforeInstantiation(beanName,mbdToUse);
  ```

  如果 InstantiationAwareBeanPostProcessor 沒有返回代理對(duì)象杠茬,調(diào)用下面的方法創(chuàng)建 Bean。

  ```java
  Object beanInstance = doCreateBean(beanName,mbcToUse,args);
  
  //創(chuàng)建 Bean 實(shí)例铲觉,利用工廠方法或者對(duì)象的構(gòu)造器創(chuàng)建出 Bean 實(shí)例澈蝙。
  createBeanInstance(beanName,mbd,args);
  
  // 創(chuàng)建實(shí)例對(duì)象后,執(zhí)行后置處理器
  // 利用 MergedBeanDefintionPostProcessor 
  applyMergedBeanDefintionPostProcessor(mbd,beanType,beanName);
  bdp.postProcessMergedBeanDefinition(mbd,beanType,beanName);
  ```

  對(duì) Bean 的屬性進(jìn)行賦值

  ```java
  populateBean(beanName,mbd,instanceWrapper);
  
  //賦值之前拿到 InstantiationAwareBeanPostProcessor 后置處理器
  //執(zhí)行 postProcessAfterInstantiation
  
  //再拿 InstantiationAwareBeanPostProcessor 后置處理器
  //執(zhí)行 postProcessPropertyValues 方法
  
  //最后一步撵幽,應(yīng)用 Bean 屬性的值灯荧,利用 setter 方法等用反射賦值。
  applyPropertyValues(beanName,mbd,bw,pvs);
  ```

  對(duì) Bean 進(jìn)行初始化

  ```java
  initializeBean(beanName,exposedObject,mbd);
  
  //執(zhí)行 Aware 接口的方法
  //判斷是否是 BeanNameAware盐杂,BeanClassLoaderAware逗载,BeanFactoryAware,利用 invoke 回調(diào)接口的方法链烈。
  invokeAwareMethods(beanName,bean);
  
  //執(zhí)行所有后置處理器初始化之前的方法
  applyBeanPostProcessorsBeforeInitialization(wrapperBean)
  //執(zhí)行后置處理器的回調(diào)方法
  BeanPostProcessor.postProcessBeforeInitialization()
    
  //執(zhí)行初始化方法
  invokeInitMethods(beanName,wrappedBean,mbd);
  //是否是 InitializingBean 接口實(shí)現(xiàn)類厉斟,執(zhí)行接口規(guī)定的初始化。
  //是否自定義初始化方法强衡。
  
  //執(zhí)行初始化之后后置處理器的方法
  applyBeanPostProcessorsAfterInitialization(wrapperBean)
  //執(zhí)行后置處理器的回調(diào)方法
  BeanPostProcessor.postProcessAfterInitialization()
  ```

  注冊(cè) Bean 的銷毀方法擦秽。不執(zhí)行方法,在容器銷毀時(shí)執(zhí)行。

- ·將創(chuàng)建的 Bean 添加到緩存 singletonObjects 中感挥。IOC 容器就可以理解為這些 Map缩搅,這些 Map 里面保存了很多單實(shí)例 Bean,環(huán)境信息触幼。
  • 檢查所有 Bean 是否實(shí)現(xiàn)了 SmartInitializingSingleton 接口硼瓣,如果是,就執(zhí)行回調(diào)方法置谦。
  1. finishRefresh 完成 BeanFactory 初始化創(chuàng)建工作堂鲤,IOC 容器創(chuàng)建完成。
  • 初始化和聲明周期有關(guān)的后置處理器

    initLifecycleProcessor()媒峡;
    
    //先從容器中找瘟栖,找不到 new 一個(gè) Default 的,并且注冊(cè)在 BeanFactory 中丝蹭,可以注入到組件中慢宗。
    //允許寫 LifecycleProcessor坪蚁, 可以在 BeanFactory 刷新完成或者關(guān)閉時(shí)調(diào)用一些方法奔穿。
    void onRefresh();
    void onClose();
    
  • 拿到前面定義的生命周期處理器,回調(diào) onRefresh 方法敏晤。

  • 發(fā)布容器刷新完成事件贱田。

    publishEvent(new ContextRefreshedEvent(this));
    

總結(jié):

Spring 創(chuàng)建 Bean 的時(shí)機(jī):

  1. 用到這個(gè) Bean 的時(shí)候,利用 getBean 創(chuàng)建 bean 后保存到容器中嘴脾。
  2. 同一創(chuàng)建所有剩下的 bean 的時(shí)候男摧,finishBeanFactoryInitialization();

后置處理器:

每一個(gè) Bean 創(chuàng)建完成后,都會(huì)使用各種后置處理器進(jìn)行處理译打,來增強(qiáng) Bean 的功能耗拓。

  1. AutowiredAnnotationBeanPostProcessor:來處理自動(dòng)注入。
  2. AnnotationAwareAspectJAutoProxyCreator:來做 AOP 功能奏司。
  3. AsyncAnnotationBeanPostProcessor:增強(qiáng)功能注解乔询。

AOP原理

整體啟動(dòng)流程:

  • 傳入配置類,創(chuàng)建 IOC 容器韵洋。

  • 注冊(cè)配置類竿刁,調(diào)用 refresh() 刷新容器。

  • registerBeanPostProcessors(beanFacotry)搪缨,注冊(cè) Bean 的后置處理器方便攔截 Bean 的創(chuàng)建食拜。

    • 獲取 IOC 容器中已經(jīng)定義了的需要?jiǎng)?chuàng)建對(duì)象的所有 BeanPostProcessor,配置類里注冊(cè)的副编。

    • 給容器中加其他的 PostProcessor负甸。

    • 優(yōu)先注冊(cè)了實(shí)現(xiàn)了 PriorityOrdered 接口的 BeanPostProcessor。

    • 再給容器中注冊(cè)實(shí)現(xiàn)了 Ordered 接口的 BeanPostProcessor。

    • 最后注冊(cè)沒實(shí)現(xiàn)優(yōu)先級(jí)接口的 BeanPostProcessor呻待。

    • 注冊(cè) BeanPostProcessor煮盼,實(shí)際上就是創(chuàng)建 BeanPostProcessor 的對(duì)象并保存在容器中。

    • 創(chuàng)建 internalAutoProxyCreator 的 BeanPostProcessor[AnnotationAwareAspectJAutoProxyCreator]

      • 創(chuàng)建 Bean 的實(shí)例
      • populateBean:給 Bean 的屬性賦值
      • initializeBean:初始化 Bean
        • invokeAwareMethods():處理 Aware 接口的方法回調(diào)带污。
        • applyBeanPostProcessorsBeforeInitialization():應(yīng)用后置處理器的 postProcessBeforeInitialization 方法僵控。
        • invokeInitMethods():執(zhí)行自定義初始化方法。
        • applyBeanPostProcessorsAfterInitialization():執(zhí)行后置處理器的 PostProcessAfterInitialization 方法鱼冀。
      • BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator) 創(chuàng)建成功报破。調(diào)用 initBeanFactory 生成 aspectJAdvisorsBuilder。
    • 把 BeanPostProcessor 注冊(cè)到 BeanFactory 中:

      beanFactory.addBeanPostProcessor(postProcessor)千绪。

    ==========以上是創(chuàng)建和注冊(cè) AnnotationAwareAspectJAutoProxyCreator 的過程=========

    AnnotationAwareAspectJAutoProxyCreator 這個(gè) BeanPostProcessor 做了什么充易?

    看給容器中注冊(cè)了什么組件,這個(gè)組件什么時(shí)候工作荸型,有什么功能盹靴?

    AnnotationAwareAspectJAutoProxyCreator => InstantiationAwareBeanPostProcessor

  • finishBeanFactoryInitialization(beanFactoty),完成 BeanFactory 的初始化工作瑞妇,創(chuàng)建剩下的單實(shí)例 Bean稿静。

    • 遍歷獲取容器中所有的 Bean,依次創(chuàng)建對(duì)象 getBean(beanName)辕狰。

    getBean->doGetBean()->getSingleton()

    • 創(chuàng)建 Bean

      【AnnotationAwareAspectJAutoProxyCreator 在所有 Bean 創(chuàng)建之前會(huì)有一個(gè)攔截改备,因?yàn)閷?shí)現(xiàn)了InstantiationAwareBeanPostProcessor,會(huì)調(diào)用 postProcessBeforeInstantiation 方法】

      • 先從緩存中獲取當(dāng)前 Bean蔓倍,如果能獲取到悬钳,說明 Bean 是之前被創(chuàng)建過的,直接使用偶翅,否則再創(chuàng)建默勾。只要?jiǎng)?chuàng)建好的 Bean 都會(huì)被緩存起來。

      • createBean()聚谁,創(chuàng)建 Bean母剥。AnnotationAwareAspectJAutoProxyCreator 會(huì)在任何 Bean 創(chuàng)建之前嘗試返回 Bean 的實(shí)例。

        【BeanPostProcessor 是在 Bean 對(duì)象創(chuàng)建完成初始化前后調(diào)用的】

        【InstantiationAwareBeanPostProcessor 是在創(chuàng)建 Bean 實(shí)例之前嘗試用后置處理器返回對(duì)象的】

        • resolveBeforeInstantiation(beanName,mbdToUse)垦巴,解析 BeforeInstantiation媳搪。希望后置處理器在此能返回一個(gè)代理對(duì)象。如果能返回代理對(duì)象就使用骤宣,如果不能就繼續(xù)秦爆。

        • resolveBeforeInstantiation 方法里,后置處理器先嘗試返回對(duì)象憔披。

          bean = applyBeanPostProcessorsBeforeInstantiation等限,拿到所有后置處理器爸吮,如果是 InstantiationAwareBeanPostProcessor,就執(zhí)行后置處理的 postProcessBeforeInstaniation 方法望门。

          if(bean != null){

          ? bean = applyBeanPostProcessorsAfterInitialization

          }

        • doCreateBean(beanName,mbdToUse,args)形娇,真正的去創(chuàng)建一個(gè) Bean 實(shí)例。

第一步

從 @EnableAspectJAutoProxy 開始分析筹误。首先關(guān)注 @Import桐早,將 AspectJAutoProxyRegistrar,給容器中導(dǎo)入 AspectJAutoProxyRegistrar厨剪。AspectJAutoProxyRegistrar 又實(shí)現(xiàn)了 ImportBeanDefinitionRegistrar 接口哄酝,這個(gè)接口可以自定義注冊(cè) Bean。

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy{}

AnnotationMetadata:當(dāng)前類的注解信息祷膳。

BeanDefinitionRegistry:BeanDefinition注冊(cè)類陶衅。

//ImportBeanDefinitionRegistrar
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry){
    //根據(jù)class指定BeanDefintion信息
        RootBeanDefinition beanDefinition = new RootBeanDefinition(A.class);
        //注冊(cè)一個(gè) Bean,指定 bean 名稱
        registry.registerBeanDefintion("rainBow",beanDefinition)
}

@EnableAspectJAutoProxy 利用 AspectJAutoProxyRegistrar 自定義給容器中注冊(cè) Bean直晨。那么它為 AOP 注冊(cè)了什么 Bean 那搀军?

可以在 AspectJAutoProxyRegistrar 的 registerBeanDefinitions 函數(shù)里尋找答案:

//AspectJAutoProxyRegistrar
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//想容器中注冊(cè)了一個(gè)名為 internalAutoProxyCreator,class 為 AnnotationAwareAspectJAutoProxyCreator 的 Bean勇皇。BeanDefinitionRegistry.registerBeanDefinition
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
  
//拿到注解相關(guān)的信息  
        AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
//根據(jù)拿到的注解的信息判斷 proxyTargetClass 和 exposeProxy 屬性
        if (enableAspectJAutoProxy != null) {
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }

            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }

    }

第一步總結(jié):利用 AspectJAutoProxyRegistrar 給容器中注冊(cè)了一個(gè) AnnotationAwareAspectJAutoProxyCreator 類型的 Bean罩句。

第二步

既然住了一個(gè) AnnotationAwareAspectJAutoProxyCreator,那么這個(gè)組件有什么作用那儒士?字面理解這個(gè) Bean 是注解模式切面自動(dòng)代理創(chuàng)建器的止。

先來看這個(gè)組件的繼承關(guān)系:

AnnotationAwareAspectJAutoProxyCreator

? ->AspectJAwareAdvisorAutoProxyCreator

? ->AbstractAdvisorAutoProxyCreator

? ->AbstractAutoProxyCreator

? implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware

最源頭實(shí)現(xiàn)了一個(gè) Bean 后置處理器的接口和一個(gè) BeanFactory 的接口。后置處理器在 Bean 初始化完成前后做事情着撩,自動(dòng)裝配 BeanFactory 到實(shí)例中。首先看看這兩個(gè)接口對(duì)應(yīng)的 set 方法在哪里實(shí)現(xiàn)的匾委。

AbstractAutoProxyCreator.setBeanFactory()

AbstractAutoProxyCreator.后置處理器相關(guān)的邏輯

AspectJAwareAdvisorAutoProxyCreator.setBeanFactory()->initBeanFactory()

AnnotationAwareAspectJAutoProxyCreator.initBeanFactory()拖叙,父類調(diào)用 setBeanFactory 的時(shí)候會(huì)調(diào)用 initBeanFactory 方法,這個(gè)方法又被子類重寫了赂乐,最后還會(huì)調(diào)用子類的 initBeanFactory 方法薯鳍。

AspectJAwareAdvisorAutoProxyCreator【InstantiationAwareBeanPostProcessor】的作用:

  • 每個(gè) Bean 創(chuàng)建之前,調(diào)用 postProcessBeforeInstantiation 方法挨措。

    關(guān)心我們加入切面的 Bean

    • 判斷當(dāng)前 Bean 是否在 advisedBeans 中(保存了所有需要增強(qiáng)的 Bean)挖滤。
    • 判斷當(dāng)前 Bean 是否是基礎(chǔ)類型,Advice浅役、Pointcut斩松、Advisor、AopInfrastructureBean觉既,或者是否是切面( @Aspect 注解)
    • 判斷是否需要跳過惧盹,獲取候選的增強(qiáng)器(切面里的通知方法)乳幸,每一個(gè)封裝的通知方法的增強(qiáng)器是 InstantiationModelAwarePointcutAdvisor,判斷每一個(gè)增強(qiáng)器是否是 AspectJPointcutAdvisor 類型钧椰。
  • 創(chuàng)建對(duì)象粹断。

  • Bean 創(chuàng)建之后,調(diào)用 postProcessAfterInitialization 方法嫡霞。

    return wrapIfNecessary(bean, beanName,cacheKey); //包裝如果需要的情況下

    • 獲取當(dāng)前 Bean 的所有增強(qiáng)器(通知方法)瓶埋。找到能在當(dāng)前 Bean 使用的增強(qiáng)器(哪些通知方法是要切入當(dāng)前 Bean 方法的)。然后給增強(qiáng)器排序诊沪。

    • 保存當(dāng)前 Bean 到 advisedBean悬赏,表示當(dāng)前 Bean 已經(jīng)被增強(qiáng)了。

    • 創(chuàng)建當(dāng)前 Bean 的代理對(duì)象娄徊,通過 proxyFactory 創(chuàng)建代理對(duì)象闽颇。需要傳入增強(qiáng)器。通過 proxyFactory 會(huì)創(chuàng)建兩種動(dòng)態(tài)代理寄锐。

      JdkDynamicAopProxy(config); jdk 動(dòng)態(tài)代理兵多。實(shí)現(xiàn)了接口就用jdk。

      ObjenesisCglibAopProxy(config); cglib 的動(dòng)態(tài)代理橄仆。

    wrapIfNecessary 執(zhí)行結(jié)束剩膘,給容器中返回當(dāng)前組件使用 cglib 增強(qiáng)了的代理對(duì)象。以后容器中獲取到的就是這個(gè)組件的代理對(duì)象盆顾,執(zhí)行目標(biāo)方法的時(shí)候怠褐,代理對(duì)象就會(huì)執(zhí)行通知方法的流程。

  • 目標(biāo)方法執(zhí)行您宪。

    容器中保存了組件的代理對(duì)象(jdk 或 cglib 增強(qiáng)后的)奈懒,這個(gè)兌現(xiàn)管理保存了詳細(xì)信息,比如增強(qiáng)器宪巨,目標(biāo)對(duì)象磷杏。

    • CglibAopProxy.intercept() 方法,攔截目標(biāo)方法執(zhí)行捏卓。

    • 根據(jù) ProxyFactory 獲取對(duì)象將要執(zhí)行的目標(biāo)方法連接器鏈 chain极祸。

      List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

      List<Object> interceptorList 保存所有攔截器,一個(gè)默認(rèn)的 ExposeInvocationInterceptor 和 自定義的增強(qiáng)器

      遍歷所有的增強(qiáng)器怠晴,將其轉(zhuǎn)為 Interceptor遥金,registry.getIntercepotr(advisor)

      如果是 MethodInterceptor,直接加入集合蒜田,如果不是稿械,使用 AdvisorAdapter 將其增強(qiáng)轉(zhuǎn)為 MethodInterceptor。

    • 如果沒有攔截器鏈物邑,直接執(zhí)行目標(biāo)方法溜哮。

      攔截器鏈:每一個(gè)通知方法又被包裝為方法攔截器滔金,利用 MethodInterceptor 機(jī)制來執(zhí)行方法。

    • 如果有攔截器鏈茂嗓,把需要執(zhí)行的目標(biāo)對(duì)象餐茵,目標(biāo)方法,連接器鏈等信息傳入創(chuàng)建一個(gè) CglibMethodInvocation 對(duì)象述吸,并調(diào)用 procceed 方法忿族,返回 retVal。

    • 攔截器鏈的觸發(fā)過程

      如果沒有攔截器執(zhí)行目標(biāo)方法蝌矛,最后一個(gè)攔截器也執(zhí)行目標(biāo)方法道批。

  • 鏈?zhǔn)将@取每一個(gè)攔截器,攔截器執(zhí)行 invoke 方法入撒,每一個(gè)連接器等待下一個(gè)攔截器執(zhí)行完成返回以后再執(zhí)行隆豹,攔截器鏈的機(jī)制,保證通知方法與目標(biāo)方法的執(zhí)行順序茅逮。

總結(jié):

  • 使用 @EnableAspectJAutoProxy 開啟 AOP 功能璃赡。

  • @EnableAspectJAutoProxy 會(huì)給容器中注冊(cè)一個(gè)組件 AnnotationAwareAspectJAutoProxyCreator。

  • AnnotationAwareAspectJAutoProxyCreator 是一個(gè)后置處理器献雅。

  • 容器的創(chuàng)建過程:

    • registerBeanPostProcessors() 注冊(cè)后置處理器: 創(chuàng)建 AnnotationAwareAspectJAutoProxyCreator 對(duì)象碉考。

    • finishBeanFactoryInitialization() 初始化剩下的單實(shí)例 Bean。

      • 創(chuàng)建業(yè)務(wù)邏輯組件和切面組件挺身。

      • AnnotationAwareAspectJAutoProxyCreator 會(huì)攔截組件的創(chuàng)建過程雨效。

      • 組件創(chuàng)建完后蛤高,判斷組件是否需要增強(qiáng)

        是:切面的通知方法撵彻,包裝成增強(qiáng)器(Advisor)艺演,給業(yè)務(wù)邏輯創(chuàng)建一個(gè)代理對(duì)象。

    • 執(zhí)行目標(biāo)方法

      • 代理對(duì)象執(zhí)行目標(biāo)方法

      • 用 CglibAopProxy.intercept 進(jìn)行攔截伍玖。

        • 得到目標(biāo)方法的攔截器鏈(增強(qiáng)器包裝成攔截器 MethodInterceptor)嫩痰。

        • 利用攔截器的鏈?zhǔn)綑C(jī)制,依次進(jìn)入每一個(gè)攔截器進(jìn)行執(zhí)行窍箍。

        • 效果:

          前置通知->目標(biāo)方法->后置通知->返回通知/異常通知

Spring 事務(wù)

入口與 AOP 一樣,通過 @EnableTransactionManagement 來進(jìn)行源碼分析丽旅。

@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement{
      boolean proxyTargetClass() default false;
      AdviceMode mode() default AdviceMode.PROXY;
}

這個(gè)注解同樣有 @Import 注解椰棘,我們來關(guān)注 TransactionManagementConfigurationSelector 這個(gè)類來看到底為 Spring 事務(wù)導(dǎo)入了什么組件。

protected String[] selectImports(AdviceMode adviceMode) {
  switch(adviceMode) {
    case PROXY:
      return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
    case ASPECTJ:
      return new String[]{"org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration"};
    default:
      return null;
  }
}

從上面這段代碼可以看出榄笙,這個(gè)注解為我們導(dǎo)入兩個(gè)組件邪狞,AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration。

我們依次來看這兩個(gè)組件就能明白 Spring 事務(wù)到底是怎么實(shí)現(xiàn)的了茅撞。

AutoProxyRegistrar

public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

  public AutoProxyRegistrar() {
  }
  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
                   Object proxyTargetClass = candidate.get("proxyTargetClass");
                if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) {
                    candidateFound = true;
                    if (mode == AdviceMode.PROXY) {
                        AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                        if ((Boolean)proxyTargetClass) {
                            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                            return;
                        }
                    }
                }
    }
}

從代碼來看帆卓,他實(shí)現(xiàn)了 ImportBeanDefinitionRegistrar 接口巨朦,功能就不用解釋了,調(diào)用 registerBeanDefinitions 方法給容器中注冊(cè) Bean 的剑令。

因?yàn)?EnableTransactionManagement 里定義的 mode 就是 AdviceMode.PROXY糊啡,而且 proxyTargetClass 是false,所以會(huì)執(zhí)行如下代碼:

AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);

給容器中注冊(cè)一個(gè) InfrastructureAdvisorAutoProxyCreator 組件吁津,這個(gè)組件也是一個(gè)后置處理器棚蓄。

作用:利用后置處理器機(jī)制,在對(duì)象創(chuàng)建以后碍脏,包裝對(duì)象梭依,返回一個(gè)代理對(duì)象(增強(qiáng)器),代理對(duì)象執(zhí)行方法典尾,利用連接器鏈進(jìn)行調(diào)用役拴。

ProxyTransactionManagementConfiguration

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    public ProxyTransactionManagementConfiguration() {
    }

    @Bean(
        name = {"org.springframework.transaction.config.internalTransactionAdvisor"}
    )
    @Role(2)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
        BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionAttributeSource(this.transactionAttributeSource());
        advisor.setAdvice(this.transactionInterceptor());
        if (this.enableTx != null) {
            advisor.setOrder((Integer)this.enableTx.getNumber("order"));
        }

        return advisor;
    }

    @Bean
    @Role(2)
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }

    @Bean
    @Role(2)
    public TransactionInterceptor transactionInterceptor() {
        TransactionInterceptor interceptor = new TransactionInterceptor();
        interceptor.setTransactionAttributeSource(this.transactionAttributeSource());
        if (this.txManager != null) {
            interceptor.setTransactionManager(this.txManager);
        }

        return interceptor;
    }
}

首先 ProxyTransactionManagementConfiguration 也是一個(gè)配置類,利用 @Bean 給容器中注冊(cè)了一些組件钾埂。

首先注冊(cè)了一個(gè) BeanFactoryTransactionAttributeSourceAdvisor 事務(wù)增強(qiáng)器河闰。事務(wù)增強(qiáng)器需要注解里面信息。

我們關(guān)注代碼中注冊(cè)時(shí)需要傳入一個(gè)事務(wù)屬性勃教,這個(gè)屬性在下面也是注入的一個(gè) Bean淤击。

advisor.setTransactionAttributeSource(this.transactionAttributeSource());

@Bean
@Role(2)
public TransactionAttributeSource transactionAttributeSource() {
  return new AnnotationTransactionAttributeSource();
}

AnnotationTransactionAttributeSource 注冊(cè)了好多的注解解析器來支持各種類型的注解,包擴(kuò) Spring 注解故源,Jta 注解污抬,Ejb3 注解等等。

public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
  this.publicMethodsOnly = publicMethodsOnly;
  this.annotationParsers = new LinkedHashSet(2);
  this.annotationParsers.add(new SpringTransactionAnnotationParser());
  if (jta12Present) {
    this.annotationParsers.add(new JtaTransactionAnnotationParser());
  }

  if (ejb3Present) {
    this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
  }

}

接下來看事務(wù)增強(qiáng)器的第二個(gè)屬性绳军,事務(wù)攔截器印机,這個(gè)屬性也是下面注冊(cè)的一個(gè) Bean。

advisor.setAdvice(this.transactionInterceptor());

@Bean
@Role(2)
public TransactionInterceptor transactionInterceptor() {
  TransactionInterceptor interceptor = new TransactionInterceptor();
  interceptor.setTransactionAttributeSource(this.transactionAttributeSource());
  if (this.txManager != null) {
    interceptor.setTransactionManager(this.txManager);
  }

  return interceptor;
}

擴(kuò)展組件

BeanFactoryPostProcessor

我們以前了解過 BeanPostProcessor门驾,它們之間有什么區(qū)別那射赛?

BeanPostProcessor:bean 后置處理器,bean 創(chuàng)建對(duì)象初始化前后進(jìn)行攔截工作的奶是。

BeanFactoryPostProcessor:beanFactory 的后置處理器楣责,在 BeanFactory 標(biāo)準(zhǔn)初始化之后調(diào)用,所有的 BeanDefifnition 都已經(jīng)保存加載到 beanFactory 中聂沙,但是 bean 的實(shí)例還未創(chuàng)建秆麸。

  • IOC 容器創(chuàng)建對(duì)象

  • invokeBeanFactoryPostProcessors(beanFactory)。

如何找到所有的 BeanFactoryPostProceessor 并執(zhí)行它們的方法:

  • 直接在 BeanFactory 中找到所有類型是 BeanFactoryPostProcessor 的組件及汉,并執(zhí)行它們的方法沮趣。
  • 在初始化創(chuàng)建其他組件前面執(zhí)行。

BeanDefinitionRegistryPostProcessor

可以將 BeanDefinitionRegistry 理解為 BeanDefinition 的保存中心坷随,以后 BeanFactory 按照 BeanDefinitionRegistry 里面保存的每一個(gè) bean 定義信息創(chuàng)建 bean 的實(shí)例房铭。

下面我們來看 BeanFactoryPostProcessor 的子接口:

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}

額外定義了一個(gè) postProcessBeanDefinitionRegistry 方法驻龟,在所有 bean 的定義信息將要被加載,bean 實(shí)例還未被創(chuàng)建時(shí)執(zhí)行缸匪,在 BeanFactoryPostProceessor 之前執(zhí)行翁狐,因?yàn)?BeanFactoryPostProceessor 是在 bean 的定義信息已經(jīng)被加載后執(zhí)行。

可以利用 BeanDefinitionRegistryPostProcessor 給容器中額外添加一些組件豪嗽。

原理:

  • IOC 創(chuàng)建對(duì)象
  • refresh()->invokeBeanFactoryPostProcessors(beanFactory)谴蔑;
  • 先從容器中獲取到所有的 BeanDefinitionRegistryPostProcessors 組件,依次觸發(fā)所有的 postProcessBeanDefinitionRegistry() 方法龟梦,再觸發(fā) BeanFactoryPostProcessor隐锭。
  • 再來從容器中找到 BeanFactoryPostProcessor 組件,一次觸發(fā) postProcessBeanFactory() 方法计贰。

ApplicationListener

監(jiān)聽容器中發(fā)布的事件钦睡,完成事件驅(qū)動(dòng)模型的開發(fā)。

public interface ApplicationListener<E extends ApplicationEvent>

監(jiān)聽 ApplicationEvent 及其子類躁倒。

基于事件開發(fā)的步驟:

  • 寫一個(gè)監(jiān)聽器來監(jiān)聽某個(gè)事件荞怒,ApplicationEvent 及其子類。

  • 或者使用 @EventListener 注解讓任意組件都能監(jiān)聽事件秧秉,使用 EventListenerMethodProcessor 這個(gè)處理器來解析這個(gè)注解褐桌。

    • 實(shí)現(xiàn)了 SmartInitializingSingleton。
  • 把監(jiān)聽器加入到容器象迎。

  • 只要容器中有相關(guān)事件的發(fā)布荧嵌,我們就能監(jiān)聽到這個(gè)事件。

    ContextRefreshedEvent:容器刷新完成(所有 Bean 都創(chuàng)建完成)會(huì)發(fā)布這個(gè)事件砾淌。

    ContextCloseEvent:關(guān)閉容器會(huì)發(fā)布這個(gè)事件啦撮。

  • 發(fā)布一個(gè)事件:applicationContext.pushlishEvent。

原理:

ContextRefreshEvent 事件

  • 容器創(chuàng)建對(duì)象:refresh()

  • finishRefresh()汪厨,容器刷新完成

  • publishEvent(new ContextRefreshedEvent(this))

    【發(fā)布流程】

    • 獲取事件多播器(派發(fā)器):getApplicaitonEvnetMulticaster()

    • multicastEvent 派發(fā)事件

    • 獲取到所有的 ApplicationListener

      如果 Listener 里有 Executor赃春,可以支持使用 Executor 進(jìn)行異步派發(fā)。

      Executor executor = getTaskExecutor();
      

      否則同步的方式直接執(zhí)行 listener 方法劫乱,里面通過 listener 回調(diào) onApplicationEvent(envet) 方法织中。

      invokeListener(listener, event);
      

SmartInitializingSingleton

所有單實(shí)例 Bean 創(chuàng)建完成之后觸發(fā)。

// 所有的單實(shí)例 Bean 創(chuàng)建完后執(zhí)行
public interface SmartInitializingSingleton{
  void afterSingletonsInstantiated();
}

過程:

  • IOC 容器創(chuàng)建對(duì)象并 refresh 容器
  • finishBeanFactoryInitialization(beanFactory)衷戈,初始化剩下的單實(shí)例 Bean抠璃。
    • 創(chuàng)建所有的單實(shí)例 Bean,for 循環(huán) + getBean() .
    • 獲取創(chuàng)建好的單實(shí)例 Bean脱惰,判斷是否是 SmartInitializingSingleton,如果是就調(diào)用 afterSingletonsInstantiated 方法窿春。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末拉一,一起剝皮案震驚了整個(gè)濱河市采盒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蔚润,老刑警劉巖磅氨,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異嫡纠,居然都是意外死亡烦租,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門除盏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來叉橱,“玉大人,你說我怎么就攤上這事者蠕∏宰#” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵踱侣,是天一觀的道長(zhǎng)粪小。 經(jīng)常有香客問我,道長(zhǎng)抡句,這世上最難降的妖魔是什么探膊? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮待榔,結(jié)果婚禮上逞壁,老公的妹妹穿的比我還像新娘。我一直安慰自己究抓,他們只是感情好猾担,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著刺下,像睡著了一般绑嘹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上橘茉,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天工腋,我揣著相機(jī)與錄音,去河邊找鬼畅卓。 笑死擅腰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的翁潘。 我是一名探鬼主播趁冈,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了渗勘?” 一聲冷哼從身側(cè)響起沐绒,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎旺坠,沒想到半個(gè)月后乔遮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡取刃,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年蹋肮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片璧疗。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡坯辩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出病毡,到底是詐尸還是另有隱情濒翻,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布啦膜,位于F島的核電站有送,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏僧家。R本人自食惡果不足惜雀摘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望八拱。 院中可真熱鬧阵赠,春花似錦、人聲如沸肌稻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽爹谭。三九已至枷邪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間诺凡,已是汗流浹背东揣。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留腹泌,地道東北人嘶卧。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像凉袱,于是被迫代替她去往敵國(guó)和親芥吟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容