Spring 源碼解析(一)

Spring 源碼解析

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

概念

Spring 源碼的核心組件:javascript

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

IOC 容器能夠理解爲一個 Map,key 就是咱們日常使用 Spring 框架時寫的 Bean Id,value 就是對應類的實例化對象。java

幾個重要的類

在開始分析源碼以前,咱們先試着瞭解幾個概念,這幾個類對於咱們理解源碼有着很大的幫助,方便對整個 Spring 源碼進行分析。spring

  1. ApplicationContext,BeanFactory
    提到 Spring 就一直說容器,這個容器咱們上面也給出了一個直觀的解釋,能夠理解爲一個 Map,用來存儲實例化的的對象,須要的時候就從容器裏面取就能夠了。那麼在代碼中的具體實現是什麼那?編程

    你們最爲熟悉的實現可能就是 ApplicationContext,它就是一個容器,而它實現了 BeanFactory 接口,能夠說 BeanFactory 就是最基礎的容器,ApplicationContext 至關於在 BeanFactory 接口增長了一些功能,它們均可以稱爲容器。緩存

    先來看看 BeanFactory 的代碼:markdown

    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 方法和一些判斷是不是單例或者原型的方法。app

    再來看 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 多了許多功能。異步

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

    • 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 文件中的 標籤,在 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 手工進行註冊。
    java 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 的建立流程。

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

      若是 InstantiationAwareBeanPostProcessor 沒有返回代理對象,調用下面的方法建立 Bean。

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

      對 Bean 的屬性進行賦值

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

      對 Bean 進行初始化

      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 chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

      List 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 方法。
      posted @ 2019-06-11 20:05 當年明月123 閱讀( ...) 評論( ...) 編輯 收藏

相關文章
相關標籤/搜索