Spring 源碼解析(一)

Spring 源碼解析

  • 第一章為源碼解析。
  • 第二章為實現一個簡單的 IOC 容器。
  • 第三章進階 Spring 插件開發。

概念

Spring 源碼的核心組件:

  • IOC 容器負責實例化,定位,配置應用程序中的對象及建立這些對象間的依賴。
  • AOP 面向切面編程,通過預編譯方式和運行期間動態代理實現功能的統一維護的一種技術。

IOC 容器可以理解為一個 Map,key 就是我們平常使用 Spring 框架時寫的 Bean Id,value 就是對應類的實例化對象。

幾個重要的類

在開始分析源碼之前,我們先試著了解幾個概念,這幾個類對于我們理解源碼有著很大的幫助,方便對整個 Spring 源碼進行分析。

  1. ApplicationContext,BeanFactory
    提到 Spring 就一直說容器,這個容器我們上面也給出了一個直觀的解釋,可以理解為一個 Map,用來存儲實例化的的對象,需要的時候就從容器里面取就可以了。那么在代碼中的具體實現是什么那?

    大家最為熟悉的實現可能就是 ApplicationContext,它就是一個容器,而它實現了 BeanFactory 接口,可以說 BeanFactory 就是最基礎的容器,ApplicationContext 相當于在 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);
        
    }
    

    整個接口定義的抽象方法其實非常簡單和直接,主要就是各種個樣的 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;
    }
    

    不僅僅實現了 BeanFactory 接口,而且實現了事件派發器,資源解析器以及環境參數相關的接口,比 BeanFactory 多了許多功能。

    下面來看看常用的容器,也就是上面接口的實現類。

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

    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 類名稱,作用域【單例或者原型】,構造函數的參數,屬性等等,這些信息也說明這個類是 Spring 用來構建 Bean 的主要的類。

    這個接口的主要實現類有 RootBeanDefinition,ChildBeanDefinition,GenericBeanDefinition等等。其中 RootBeanDefinition 最為常用,相當于 xml 文件中的 <bean> 標簽,在 xml 中可以配置 parent 屬性,這里的父就是 RootBeanDefinition,子就是 ChildBeanDefinition。

  3. BeanDefinitionRegistry
    既然有了材料 BeanDefinition,下面一定需要一個操作它的類,BeanDefinitionRegistry 就是一個用來幫我們操作 BeanDefinition 的接口,它的里面有許多操作 BeanDefinition 的方法,包括通過 BeanDefinition 注冊 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 方法將一個 Bean 注冊到容器中。調用 BeanDefinitionRegistry.registerBeanDefinition 手工進行注冊。

    BeanDefinitionRegistry registry = context.getRegistry();
    boolean definition = registry.containsBeanDefinition("person");
    
  4. BeanPostProcessor
    BeanPostProcessor,bean 的后置處理器,在 bean 初始化前后進行一些處理工作。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;
     }
    }
    

    由此衍生出來的后置處理器非常多,處理時機也不一樣,我們會在后面的源碼分析對這些后置處理器的實現原理和操作時機進行一個總結。
    Spring 底層對 BeanPostProcessor 的使用:bean 賦值,注入其他組件,@Autowired,聲明周期注解功能,@Async等等。

  5. ApplicationContextAware
    自定義組件想要使用 Spring 容器底層的一些組件(ApplicationContext,BeanFactory,xxx)等等,需要自定義組件實現 xxxAware 接口。在創建對象的時候,會調用接口規定的方法注入相關組件。ApplicationContextAware 會將 IOC 容器傳入到組件中,BeanNameAware 會講當前實例在 IOC 容器中 Bean 的名字傳入到實例中。這些 Aware 會有對應的 AwareProcessor 來進行邏輯處理。

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

    如果想往組件中注入容器可以實現 ApplicationContextAware 接口,然后通過 setApplicationContext 保存起來。 我們對 Spring 功能進行擴展時常常喲昂到這些 Aware。

  6. ApplicationListener 與 ApplicationEventMulticaster
    這兩個組件是 Spring 事件驅動模型用到的組件,ApplicationListener:事件監聽。ApplicationEventMulticaster:事件派發。

Bean 的生命周期

Bean 的聲明周期指的是 Bean 的創建-->初始化-->銷毀的過程,Spring 把這個過程全部交給容器來管理。我們可以自定義初始化和銷毀方法,容器在 Bean 進行到當前生命周期的時候來調用我們自定一的初始化和銷毀方法。

構造(對象創建)
單實例:在容器啟動的時候創建對象。
多實例:在每次獲取的時候創建對象,調用 getBean 方法時。

初始化
對象創建完成,并賦值好,調用初始化方法

銷毀
單實例:容器關閉的時候。
多實例:容器會創建 Bean, 但不會管理 Bean,容器不會調用銷毀方法。

Bean 的生命周期要比上面寫的更加復雜,我們在分析完源碼后會對這部分進行一個總結。

幾個重要的注解

@Import,快速給容器中導入一個組件,@Import(Color.class) 相當于一個無參構造函數。id 默認是全類名。

@Conditional 滿足一定條件才給容器中注冊bean,這個可以用來讓兩個bean形成依賴,可以用在方法上,也可以用在類上。這個注解在 SpringBoot 用的非常多。

最后說說 @Autowired 和 @Resource 的區別:
@Autowired 自動注入默認按照 type 注入,即按照 .class 查找。如果找到多個相同類型的組件,在將屬性的名稱作為組件的 id 去容器中查找。使用 @Qualifier("bookDao") 與 @Autowired 組合可以明確指定需要裝配的 Bean,通過 id。
@Autowired(require=false) 有就裝配,沒有就變為 null。

Spring 還支持 JSR250 和 JSR330 里的 @Resource 和 @Inject 注解。Java 規范的注解。@Resource 和 @Autowired 一樣實現自動裝配,默認按照屬性名稱進行自動裝配。不支持 @Primary,也不支持 @Autowired(require=false)。
@Inject 需要額外導入包,功能和 @Autowired 一樣,不支持 require=false;
@Autowired 可以標注在構造器、參數、方法、屬性上。

提出問題

有了一些概念后,我們心里一定會有一些問題,同時帶著問題去看源碼也有助于我們更加快速地切入到 Spring 得核心,不墨跡,直給。

  1. 容器時怎么創建得,創建時都要做哪些工作。
  2. Spring 為什么要用 BeanDefintion 去構造 Bean。
  3. Spring 用 BeanDefintion 去構建 Bean 得流程是什么?
  4. Spring AOP 在 Spring 框架得基礎上做了什么?

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

容器創建和初始化過程

還是從下面這段代碼開始

AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Config.class);

new 容器的過程到底執行了什么操作那?前兩步是預處理和配置類的解析工作,我們直接看 refresh 方法,這個方法就是容器的創建和刷新以及 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() 刷新前的預處理
  • initPropertySources,字面上理解就是初始化一些屬性,但是方法體是空的,留給子類去實現。子類可以自定義個性化屬性設置方法。
  • getEnvironment().validateRequiredProperties(),屬性校驗。
  • earlyApplicationEvents,用來保存容器中的一些早期的事件。等事件派發器初始化好了之后再把它們派發出去。
  1. obtainFreshBeanFactory() 獲取 Bean 工廠。
  • refreshBeanFactory(),刷新【創建】 BeanFactory。

    在 GenericApplicationContext 里無參構造器創建一個 BeanFactory 對象。

    this.beanFactory = new DefaultListableBeanFactory();
    

    設置一個 Id。

  • getBeanFactory(),返回剛才 GenericApplicationContext 創建的 BeanFactory 對象。剛創建,里面都是默認的配置。

  • 將創建的 BeanFactory【DefaultListableBeanFactory】返回。

  1. prepareBeanFactory(),BeanFactory 的預準備工作,BeanFactory 進行一些設置。
  • 設置 BeanFactory 的類加載器、支持表達式解析器。。。

  • 添加 部分的BeanPostProcessor【ApplicationContextAwareProcessor】

  • 設置忽略自動裝配的接口,EnvironmentAware、EmbeddedValueResolverAware。。。

  • 注冊可以解析的自動裝配,我們可以在任何組件中自動注入,ResourceLoader,BeanFactory,ApplicationContext。

  • 添加 BeanPostProcessor【ApplicationListenerDetector】。

  • 添加編譯時的 AspectJ。

  • 給 BeanFactory 中注冊一些能用的組件。

    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 準備工作完成后進行的后置處理工作,子類通過重寫這個方法來在 BeanFactory 創建并預備完成以后做進一步的設置。

=============================以上是 BeanFactory 創建及準備================================

  1. invokeBeanFactoryPostProcessors(beanFactory),執行 BeanFactoryPostProcessor。

BeanFactoryProcessor:BeanFactory 的后置處理器,在 BeanFactory 標準初始化執行的 Processor,標準初始化就是以上四部。

兩個主要接口,BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor(可以用這個來注冊一些新的組件 )。

執行 BeanPostProcessor 的方法:

先執行 BeanDefintionRegistryPostProcessor

  • 獲取所有的 BeanDefinitionRegistryPostProcessor。

  • 對于實現了 PriorityOrdered 優先級接口的 BeanDefinitionRegistryPostProcessor

    postProcessor.postProcessBeanDefinitionRegistry(registry)

  • 對于實現了 Ordered 順序接口的 BeanDefinitionRegistryPostProcessor

    postProcessor.postProcessBeanDefinitionRegistry(registry)

  • 最后執行沒有實現任何優先級或者是順序接口的 BeanDefinitionRegistryPostProcessor

    postProcessor.postProcessBeanDefinitionRegistry(registry)

在執行 BeanFactoryPostProcessor 的方法

  • 流程和 BeanDefinitionRegistryPostProcessor 一模一樣。
  1. registerBeanPostProcessors,注冊 BeanPostProcessor,Bean 的后置處理器【攔截 Bean 的創建過程】。

不同接口類型的 BeanPostProcessor,在 Bean 創建前后的執行時機是不一樣的。

BeanPostProcessor

DestructionAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor

SmartInstantiationAwareBeanPostProcessor

MergedBeanDefinitionPostProcessor【internalPostProcessors】

  • 獲取所有的 BeanPostProcessor,后置處理器都默認可以有 PriorityOrdered,Ordered 來指定優先級。

  • 先注冊 PriorityOrdered 優先級接口的 BeanPostProcessor,把每一個 BeanPostProcessor 添加到 BeanFactory 中。

    beanFactory.addBeanPostProcessor(postProcessor)
    
  • 再注冊 Ordered 接口的。

  • 最后注冊沒有實現任何優先級接口的。

  • 最終注冊,MergedBeanDefinitionPostProcessor。

  • 注冊一個 ApplicationListenerDetector,來在 Bean 創建完成后檢查是否是 ApplicationListener,如果是

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

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

    如果有賦值給 messageSource 屬性,如果沒有自己創建一個 DelegatingMessageSource。

    MessageSource 取出國際化配置文件中的某個 key 值,能按照區域信息獲取。

  • 把創建好的 MessageSource 注冊到容器中,以后獲取國際化配置文件的值的時候,可以自動注入 MessageSource,調用 getMessage 方法就可以獲取到了。

    beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource)
    
  1. initApplicationEventMulticaster,初始化事件派發器。
  • 獲取 BeanFactory。
  • 從 BeanFactory 中獲取 ID 為 applicationEventMulticaster,類型為 ApplicationEventMulticaster 的派發器。
  • 如果上一步沒有配置事件派發器,就創建一個 SimpleApplicationEventMulticaster,為我們派發事件。
  • 將創建的 ApplicationEventMulticaster 添加到 BeanFactory 中,以后其他組件自動注入即可。
  1. onRefresh,留給子容器(子類),重寫 onRefresh 方法,在容器刷新時可以再自定義邏輯。

  2. registerListeners,給容器中把項目里的 ApplicationListener 注冊進來。

  • 從容器中拿到所有的 ApplicationListener 組件,將每個監聽器添加到事件派發器中。

    getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName)
    
  • 派發之前步驟產生的事件,派發器沒初始化之前的。

  1. finishBeanFactoryInitialization,初始化所有剩下的單實例 Bean。
//初始化所有剩下的單實例 bean。
beanFactory.preInstantiateSingletons();
  • 獲取容器中的所有 BeanDefinitions,依次進行初始化和創建對象。

  • 如果 Bean 不是抽象的,是單實例,不是懶加載的,就開始創建單例 Bean。

    判斷是否是 FactoryBean,即是否實現了 FactoryBean 接口的 Bean,如果是就用工廠方法創建對象。

    如果不是工廠 Bean,利用 getBean(beanName) 創建對象。

    • getBean(beanName),就是自己寫測試類的那個 getBean。

    • 調用 doGetBean(name,null,null,false)。

    • 先獲取緩存中保存的單實例 Bean,如果能獲取到說明這個 Bean 之前被創建過了(所有創建過的單實例 Bean 都會被緩存起來)。

      //保存單實例 Bean 的
      private final Map<String,Object> singletonObjects = new ConcurrentHashMap<String,Object>(256);
      
- 緩存中獲取不到,開始 Bean 的創建對象流程。

- 標記當前 Bean 已經被創建。

- 獲取 Bean 的定義信息。

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

- 啟動單實例 Bean 的創建流程。

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

  如果 InstantiationAwareBeanPostProcessor 沒有返回代理對象,調用下面的方法創建 Bean。

  ```java
  Object beanInstance = doCreateBean(beanName,mbcToUse,args);
  
  //創建 Bean 實例,利用工廠方法或者對象的構造器創建出 Bean 實例。
  createBeanInstance(beanName,mbd,args);
  
  // 創建實例對象后,執行后置處理器
  // 利用 MergedBeanDefintionPostProcessor 
  applyMergedBeanDefintionPostProcessor(mbd,beanType,beanName);
  bdp.postProcessMergedBeanDefinition(mbd,beanType,beanName);
  ```

  對 Bean 的屬性進行賦值

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

  對 Bean 進行初始化

  ```java
  initializeBean(beanName,exposedObject,mbd);
  
  //執行 Aware 接口的方法
  //判斷是否是 BeanNameAware,BeanClassLoaderAware,BeanFactoryAware,利用 invoke 回調接口的方法。
  invokeAwareMethods(beanName,bean);
  
  //執行所有后置處理器初始化之前的方法
  applyBeanPostProcessorsBeforeInitialization(wrapperBean)
  //執行后置處理器的回調方法
  BeanPostProcessor.postProcessBeforeInitialization()
    
  //執行初始化方法
  invokeInitMethods(beanName,wrappedBean,mbd);
  //是否是 InitializingBean 接口實現類,執行接口規定的初始化。
  //是否自定義初始化方法。
  
  //執行初始化之后后置處理器的方法
  applyBeanPostProcessorsAfterInitialization(wrapperBean)
  //執行后置處理器的回調方法
  BeanPostProcessor.postProcessAfterInitialization()
  ```

  注冊 Bean 的銷毀方法。不執行方法,在容器銷毀時執行。

- ·將創建的 Bean 添加到緩存 singletonObjects 中。IOC 容器就可以理解為這些 Map,這些 Map 里面保存了很多單實例 Bean,環境信息。
  • 檢查所有 Bean 是否實現了 SmartInitializingSingleton 接口,如果是,就執行回調方法。
  1. finishRefresh 完成 BeanFactory 初始化創建工作,IOC 容器創建完成。
  • 初始化和聲明周期有關的后置處理器

    initLifecycleProcessor();
    
    //先從容器中找,找不到 new 一個 Default 的,并且注冊在 BeanFactory 中,可以注入到組件中。
    //允許寫 LifecycleProcessor, 可以在 BeanFactory 刷新完成或者關閉時調用一些方法。
    void onRefresh();
    void onClose();
    
  • 拿到前面定義的生命周期處理器,回調 onRefresh 方法。

  • 發布容器刷新完成事件。

    publishEvent(new ContextRefreshedEvent(this));
    

總結:

Spring 創建 Bean 的時機:

  1. 用到這個 Bean 的時候,利用 getBean 創建 bean 后保存到容器中。
  2. 同一創建所有剩下的 bean 的時候,finishBeanFactoryInitialization();

后置處理器:

每一個 Bean 創建完成后,都會使用各種后置處理器進行處理,來增強 Bean 的功能。

  1. AutowiredAnnotationBeanPostProcessor:來處理自動注入。
  2. AnnotationAwareAspectJAutoProxyCreator:來做 AOP 功能。
  3. AsyncAnnotationBeanPostProcessor:增強功能注解。

AOP原理

整體啟動流程:

  • 傳入配置類,創建 IOC 容器。

  • 注冊配置類,調用 refresh() 刷新容器。

  • registerBeanPostProcessors(beanFacotry),注冊 Bean 的后置處理器方便攔截 Bean 的創建。

    • 獲取 IOC 容器中已經定義了的需要創建對象的所有 BeanPostProcessor,配置類里注冊的。

    • 給容器中加其他的 PostProcessor。

    • 優先注冊了實現了 PriorityOrdered 接口的 BeanPostProcessor。

    • 再給容器中注冊實現了 Ordered 接口的 BeanPostProcessor。

    • 最后注冊沒實現優先級接口的 BeanPostProcessor。

    • 注冊 BeanPostProcessor,實際上就是創建 BeanPostProcessor 的對象并保存在容器中。

    • 創建 internalAutoProxyCreator 的 BeanPostProcessor[AnnotationAwareAspectJAutoProxyCreator]

      • 創建 Bean 的實例
      • populateBean:給 Bean 的屬性賦值
      • initializeBean:初始化 Bean
        • invokeAwareMethods():處理 Aware 接口的方法回調。
        • applyBeanPostProcessorsBeforeInitialization():應用后置處理器的 postProcessBeforeInitialization 方法。
        • invokeInitMethods():執行自定義初始化方法。
        • applyBeanPostProcessorsAfterInitialization():執行后置處理器的 PostProcessAfterInitialization 方法。
      • BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator) 創建成功。調用 initBeanFactory 生成 aspectJAdvisorsBuilder。
    • 把 BeanPostProcessor 注冊到 BeanFactory 中:

      beanFactory.addBeanPostProcessor(postProcessor)。

    ==========以上是創建和注冊 AnnotationAwareAspectJAutoProxyCreator 的過程=========

    AnnotationAwareAspectJAutoProxyCreator 這個 BeanPostProcessor 做了什么?

    看給容器中注冊了什么組件,這個組件什么時候工作,有什么功能?

    AnnotationAwareAspectJAutoProxyCreator => InstantiationAwareBeanPostProcessor

  • finishBeanFactoryInitialization(beanFactoty),完成 BeanFactory 的初始化工作,創建剩下的單實例 Bean。

    • 遍歷獲取容器中所有的 Bean,依次創建對象 getBean(beanName)。

    getBean->doGetBean()->getSingleton()

    • 創建 Bean

      【AnnotationAwareAspectJAutoProxyCreator 在所有 Bean 創建之前會有一個攔截,因為實現了InstantiationAwareBeanPostProcessor,會調用 postProcessBeforeInstantiation 方法】

      • 先從緩存中獲取當前 Bean,如果能獲取到,說明 Bean 是之前被創建過的,直接使用,否則再創建。只要創建好的 Bean 都會被緩存起來。

      • createBean(),創建 Bean。AnnotationAwareAspectJAutoProxyCreator 會在任何 Bean 創建之前嘗試返回 Bean 的實例。

        【BeanPostProcessor 是在 Bean 對象創建完成初始化前后調用的】

        【InstantiationAwareBeanPostProcessor 是在創建 Bean 實例之前嘗試用后置處理器返回對象的】

        • resolveBeforeInstantiation(beanName,mbdToUse),解析 BeforeInstantiation。希望后置處理器在此能返回一個代理對象。如果能返回代理對象就使用,如果不能就繼續。

        • resolveBeforeInstantiation 方法里,后置處理器先嘗試返回對象。

          bean = applyBeanPostProcessorsBeforeInstantiation,拿到所有后置處理器,如果是 InstantiationAwareBeanPostProcessor,就執行后置處理的 postProcessBeforeInstaniation 方法。

          if(bean != null){

          ? bean = applyBeanPostProcessorsAfterInitialization

          }

        • doCreateBean(beanName,mbdToUse,args),真正的去創建一個 Bean 實例。

第一步

從 @EnableAspectJAutoProxy 開始分析。首先關注 @Import,將 AspectJAutoProxyRegistrar,給容器中導入 AspectJAutoProxyRegistrar。AspectJAutoProxyRegistrar 又實現了 ImportBeanDefinitionRegistrar 接口,這個接口可以自定義注冊 Bean。

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

AnnotationMetadata:當前類的注解信息。

BeanDefinitionRegistry:BeanDefinition注冊類。

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

@EnableAspectJAutoProxy 利用 AspectJAutoProxyRegistrar 自定義給容器中注冊 Bean。那么它為 AOP 注冊了什么 Bean 那?

可以在 AspectJAutoProxyRegistrar 的 registerBeanDefinitions 函數里尋找答案:

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

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

    }

第一步總結:利用 AspectJAutoProxyRegistrar 給容器中注冊了一個 AnnotationAwareAspectJAutoProxyCreator 類型的 Bean。

第二步

既然住了一個 AnnotationAwareAspectJAutoProxyCreator,那么這個組件有什么作用那?字面理解這個 Bean 是注解模式切面自動代理創建器。

先來看這個組件的繼承關系:

AnnotationAwareAspectJAutoProxyCreator

? ->AspectJAwareAdvisorAutoProxyCreator

? ->AbstractAdvisorAutoProxyCreator

? ->AbstractAutoProxyCreator

? implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware

最源頭實現了一個 Bean 后置處理器的接口和一個 BeanFactory 的接口。后置處理器在 Bean 初始化完成前后做事情,自動裝配 BeanFactory 到實例中。首先看看這兩個接口對應的 set 方法在哪里實現的。

AbstractAutoProxyCreator.setBeanFactory()

AbstractAutoProxyCreator.后置處理器相關的邏輯

AspectJAwareAdvisorAutoProxyCreator.setBeanFactory()->initBeanFactory()

AnnotationAwareAspectJAutoProxyCreator.initBeanFactory(),父類調用 setBeanFactory 的時候會調用 initBeanFactory 方法,這個方法又被子類重寫了,最后還會調用子類的 initBeanFactory 方法。

AspectJAwareAdvisorAutoProxyCreator【InstantiationAwareBeanPostProcessor】的作用:

  • 每個 Bean 創建之前,調用 postProcessBeforeInstantiation 方法。

    關心我們加入切面的 Bean

    • 判斷當前 Bean 是否在 advisedBeans 中(保存了所有需要增強的 Bean)。
    • 判斷當前 Bean 是否是基礎類型,Advice、Pointcut、Advisor、AopInfrastructureBean,或者是否是切面( @Aspect 注解)
    • 判斷是否需要跳過,獲取候選的增強器(切面里的通知方法),每一個封裝的通知方法的增強器是 InstantiationModelAwarePointcutAdvisor,判斷每一個增強器是否是 AspectJPointcutAdvisor 類型。
  • 創建對象。

  • Bean 創建之后,調用 postProcessAfterInitialization 方法。

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

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

    • 保存當前 Bean 到 advisedBean,表示當前 Bean 已經被增強了。

    • 創建當前 Bean 的代理對象,通過 proxyFactory 創建代理對象。需要傳入增強器。通過 proxyFactory 會創建兩種動態代理。

      JdkDynamicAopProxy(config); jdk 動態代理。實現了接口就用jdk。

      ObjenesisCglibAopProxy(config); cglib 的動態代理。

    wrapIfNecessary 執行結束,給容器中返回當前組件使用 cglib 增強了的代理對象。以后容器中獲取到的就是這個組件的代理對象,執行目標方法的時候,代理對象就會執行通知方法的流程。

  • 目標方法執行。

    容器中保存了組件的代理對象(jdk 或 cglib 增強后的),這個兌現管理保存了詳細信息,比如增強器,目標對象。

    • CglibAopProxy.intercept() 方法,攔截目標方法執行。

    • 根據 ProxyFactory 獲取對象將要執行的目標方法連接器鏈 chain。

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

      List<Object> interceptorList 保存所有攔截器,一個默認的 ExposeInvocationInterceptor 和 自定義的增強器

      遍歷所有的增強器,將其轉為 Interceptor,registry.getIntercepotr(advisor)

      如果是 MethodInterceptor,直接加入集合,如果不是,使用 AdvisorAdapter 將其增強轉為 MethodInterceptor。

    • 如果沒有攔截器鏈,直接執行目標方法。

      攔截器鏈:每一個通知方法又被包裝為方法攔截器,利用 MethodInterceptor 機制來執行方法。

    • 如果有攔截器鏈,把需要執行的目標對象,目標方法,連接器鏈等信息傳入創建一個 CglibMethodInvocation 對象,并調用 procceed 方法,返回 retVal。

    • 攔截器鏈的觸發過程

      如果沒有攔截器執行目標方法,最后一個攔截器也執行目標方法。

  • 鏈式獲取每一個攔截器,攔截器執行 invoke 方法,每一個連接器等待下一個攔截器執行完成返回以后再執行,攔截器鏈的機制,保證通知方法與目標方法的執行順序。

總結:

  • 使用 @EnableAspectJAutoProxy 開啟 AOP 功能。

  • @EnableAspectJAutoProxy 會給容器中注冊一個組件 AnnotationAwareAspectJAutoProxyCreator。

  • AnnotationAwareAspectJAutoProxyCreator 是一個后置處理器。

  • 容器的創建過程:

    • registerBeanPostProcessors() 注冊后置處理器: 創建 AnnotationAwareAspectJAutoProxyCreator 對象。

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

      • 創建業務邏輯組件和切面組件。

      • AnnotationAwareAspectJAutoProxyCreator 會攔截組件的創建過程。

      • 組件創建完后,判斷組件是否需要增強

        是:切面的通知方法,包裝成增強器(Advisor),給業務邏輯創建一個代理對象。

    • 執行目標方法

      • 代理對象執行目標方法

      • 用 CglibAopProxy.intercept 進行攔截。

        • 得到目標方法的攔截器鏈(增強器包裝成攔截器 MethodInterceptor)。

        • 利用攔截器的鏈式機制,依次進入每一個攔截器進行執行。

        • 效果:

          前置通知->目標方法->后置通知->返回通知/異常通知

Spring 事務

入口與 AOP 一樣,通過 @EnableTransactionManagement 來進行源碼分析。

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

這個注解同樣有 @Import 注解,我們來關注 TransactionManagementConfigurationSelector 這個類來看到底為 Spring 事務導入了什么組件。

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;
  }
}

從上面這段代碼可以看出,這個注解為我們導入兩個組件,AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration。

我們依次來看這兩個組件就能明白 Spring 事務到底是怎么實現的了。

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;
                        }
                    }
                }
    }
}

從代碼來看,他實現了 ImportBeanDefinitionRegistrar 接口,功能就不用解釋了,調用 registerBeanDefinitions 方法給容器中注冊 Bean 的。

因為 EnableTransactionManagement 里定義的 mode 就是 AdviceMode.PROXY,而且 proxyTargetClass 是false,所以會執行如下代碼:

AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);

給容器中注冊一個 InfrastructureAdvisorAutoProxyCreator 組件,這個組件也是一個后置處理器。

作用:利用后置處理器機制,在對象創建以后,包裝對象,返回一個代理對象(增強器),代理對象執行方法,利用連接器鏈進行調用。

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 也是一個配置類,利用 @Bean 給容器中注冊了一些組件。

首先注冊了一個 BeanFactoryTransactionAttributeSourceAdvisor 事務增強器。事務增強器需要注解里面信息。

我們關注代碼中注冊時需要傳入一個事務屬性,這個屬性在下面也是注入的一個 Bean。

advisor.setTransactionAttributeSource(this.transactionAttributeSource());

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

AnnotationTransactionAttributeSource 注冊了好多的注解解析器來支持各種類型的注解,包擴 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());
  }

}

接下來看事務增強器的第二個屬性,事務攔截器,這個屬性也是下面注冊的一個 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;
}

擴展組件

BeanFactoryPostProcessor

我們以前了解過 BeanPostProcessor,它們之間有什么區別那?

BeanPostProcessor:bean 后置處理器,bean 創建對象初始化前后進行攔截工作的。

BeanFactoryPostProcessor:beanFactory 的后置處理器,在 BeanFactory 標準初始化之后調用,所有的 BeanDefifnition 都已經保存加載到 beanFactory 中,但是 bean 的實例還未創建。

  • IOC 容器創建對象

  • invokeBeanFactoryPostProcessors(beanFactory)。

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

  • 直接在 BeanFactory 中找到所有類型是 BeanFactoryPostProcessor 的組件,并執行它們的方法。
  • 在初始化創建其他組件前面執行。

BeanDefinitionRegistryPostProcessor

可以將 BeanDefinitionRegistry 理解為 BeanDefinition 的保存中心,以后 BeanFactory 按照 BeanDefinitionRegistry 里面保存的每一個 bean 定義信息創建 bean 的實例。

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

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

額外定義了一個 postProcessBeanDefinitionRegistry 方法,在所有 bean 的定義信息將要被加載,bean 實例還未被創建時執行,在 BeanFactoryPostProceessor 之前執行,因為 BeanFactoryPostProceessor 是在 bean 的定義信息已經被加載后執行。

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

原理:

  • IOC 創建對象
  • refresh()->invokeBeanFactoryPostProcessors(beanFactory);
  • 先從容器中獲取到所有的 BeanDefinitionRegistryPostProcessors 組件,依次觸發所有的 postProcessBeanDefinitionRegistry() 方法,再觸發 BeanFactoryPostProcessor。
  • 再來從容器中找到 BeanFactoryPostProcessor 組件,一次觸發 postProcessBeanFactory() 方法。

ApplicationListener

監聽容器中發布的事件,完成事件驅動模型的開發。

public interface ApplicationListener<E extends ApplicationEvent>

監聽 ApplicationEvent 及其子類。

基于事件開發的步驟:

  • 寫一個監聽器來監聽某個事件,ApplicationEvent 及其子類。

  • 或者使用 @EventListener 注解讓任意組件都能監聽事件,使用 EventListenerMethodProcessor 這個處理器來解析這個注解。

    • 實現了 SmartInitializingSingleton。
  • 把監聽器加入到容器。

  • 只要容器中有相關事件的發布,我們就能監聽到這個事件。

    ContextRefreshedEvent:容器刷新完成(所有 Bean 都創建完成)會發布這個事件。

    ContextCloseEvent:關閉容器會發布這個事件。

  • 發布一個事件:applicationContext.pushlishEvent。

原理:

ContextRefreshEvent 事件

  • 容器創建對象:refresh()

  • finishRefresh(),容器刷新完成

  • publishEvent(new ContextRefreshedEvent(this))

    【發布流程】

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

    • multicastEvent 派發事件

    • 獲取到所有的 ApplicationListener

      如果 Listener 里有 Executor,可以支持使用 Executor 進行異步派發。

      Executor executor = getTaskExecutor();
      

      否則同步的方式直接執行 listener 方法,里面通過 listener 回調 onApplicationEvent(envet) 方法。

      invokeListener(listener, event);
      

SmartInitializingSingleton

所有單實例 Bean 創建完成之后觸發。

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

過程:

  • IOC 容器創建對象并 refresh 容器
  • finishBeanFactoryInitialization(beanFactory),初始化剩下的單實例 Bean。
    • 創建所有的單實例 Bean,for 循環 + getBean() .
    • 獲取創建好的單實例 Bean,判斷是否是 SmartInitializingSingleton,如果是就調用 afterSingletonsInstantiated 方法。
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容