超實用的 Spring 註解驅動開發技術

前言

如果你之前一直在使用 Spring、Spring MVC 框架,那麼一定需要編寫大量的 xml 配置檔案。如今,Spring Boot、Spring Cloud 興起之後,其底層都是基於 Spring 註解驅動,使用大量的註解替代原先的 xml 配置檔案,透過學習 Spring 註解驅動開發,瞭解每個註解的基本使用以及背後的原理,便於以後我們深入學習與使用 Spring Boot、Spring Cloud 框架。

前期準備工作

建立專案

超實用的 Spring 註解驅動開發技術

超實用的 Spring 註解驅動開發技術

next→next→finish→專案建立成功。

超實用的 Spring 註解驅動開發技術

引入依賴

<!—— https://mvnrepository。com/artifact/org。springframework/spring-context ——> org。springframework spring-context 4。3。25。RELEASE

成功引入依賴:

超實用的 Spring 註解驅動開發技術

容器

概述

Spring 之所以被廣泛使用,是因為對於開發大型專案及其方便簡單,這一切離不開 Spring 容器幫助我們管理 bean 的生命週期,那麼 Spring 容器到底是什麼呢?

bean 是 Spring 的的核心組成,而 Spring 容器就是用於管理這些物件的生命週期,例如:建立、銷燬等。

專案中我們透過 ApplicationContext 的實現類來獲取上下文,獲取容器中的 bean 的元資料。

從程式碼上講:一個 Spring 容器就是某個實現了 ApplicationContext 介面的類的例項。也就是說,從程式碼層面,Spring 容器其實就是一個 ApplicationContext(一個例項化物件)。

從原始碼角度來說,Spring 容器就是實現了 ApplicationContext 類的例項,獲取當前環境的例項即可獲取容器的內容,不同的專案環境上下文的實現類不同。

如:

# 實現 AbstractApplicationContext,xml 和註解都可以初始化 public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry # Spring Boot 中提供的實現,需要 Web Server 環境下使用 public class AnnotationConfigReactiveWebServerApplicationContext extends ReactiveWebServerApplicationContext implements AnnotationConfigRegistry

超實用的 Spring 註解驅動開發技術

超實用的 Spring 註解驅動開發技術

容器的功能

超實用的 Spring 註解驅動開發技術

容器的分類及特點

超實用的 Spring 註解驅動開發技術

容器的執行原理

建立方式

//建立基於註解的 springIOC 容器ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig。class);//建立基於配置檔案的 springIOC 容器ApplicationContext applicationContext = new ClassPathXmlApplicationContext(“/spring-app。xml”);// 建立基於註解的 WebServer 環境的 springIOC 容器,等等…………。。。。ApplicationContext applicationContext = new AnnotationConfigServletWebServerApplicationContext();

執行原理

本文以 AnnotationConfigApplicationContext 為例,AnnotationConfigApplicationContext 構造器原始碼,用於初始化容器。

public AnnotationConfigApplicationContext(Class<?>。。。 annotatedClasses) { //1。會首先呼叫父類 GenericApplicationContext 中的構造方法,初始化工廠 bean 為 new DefaultListableBeanFactory() //2。呼叫自己的構造方法,初始化了一個讀取器:AnnotatedBeanDefinitionReader reader;一個掃描器:ClassPathBeanDefinitionScanner scanner //3。在 reader 的初始化構造方法中,還註冊了 6 個 post processors this(); //註冊 bean,註冊就是把 bean 都放在某個地方,一個併發 map 中,Map beanDefinitionMap //這呼叫了 AnnotatedBeanDefinitionReader reader 的註冊方法 //只註冊了 6 個 post process 類 register(annotatedClasses); //實現的 bean 的初始化; //自定義的 bean 也在這裡註冊並初始化 refresh(); }

1. 註冊容器 register()

原始碼解析:

public void register(Class<?>。。。 annotatedClasses) { Assert。notEmpty(annotatedClasses, “At least one annotated class must be specified”); this。reader。register(annotatedClasses); }

void doRegisterBean(Class annotatedClass, @Nullable Supplier instanceSupplier, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer。。。 definitionCustomizers) { //得到 bean 的描述資訊,比如 bean 的註解,作用範圍,是否懶載入,注入方式等 AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass); //被條件註解@Conditional 註釋的 bean 跳過註冊 if (this。conditionEvaluator。shouldSkip(abd。getMetadata())) { return; } abd。setInstanceSupplier(instanceSupplier); //解析 bean 的 Scope,比如是否單例 singleton 還是其他 ScopeMetadata scopeMetadata = this。scopeMetadataResolver。resolveScopeMetadata(abd); abd。setScope(scopeMetadata。getScopeName()); //生成 bean name,預設就是類名小寫 String beanName = (name != null ? name : this。beanNameGenerator。generateBeanName(abd, this。registry)); //透過判斷註解內容,設定一些公共屬性,比如是否懶載入,優先順序等 AnnotationConfigUtils。processCommonDefinitionAnnotations(abd); if (qualifiers != null) { for (Class<? extends Annotation> qualifier : qualifiers) { if (Primary。class == qualifier) { abd。setPrimary(true); } else if (Lazy。class == qualifier) { abd。setLazyInit(true); } else { abd。addQualifier(new AutowireCandidateQualifier(qualifier)); } } } for (BeanDefinitionCustomizer customizer : definitionCustomizers) { customizer。customize(abd); } BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); definitionHolder = AnnotationConfigUtils。applyScopedProxyMode(scopeMetadata, definitionHolder, this。registry); BeanDefinitionReaderUtils。registerBeanDefinition(definitionHolder, this。registry);}

register 主要分為三步(只要是註冊 BeanDefinition,都是這 3 步):

根據 class 檔案獲取 BeanDefinition,這裡是其實現類 AnnotatedGenericBeanDefinition abd;

將 BeanDefinition 放到 BeanDefinitionHolder 中進一步封裝;

最後一行,執行註冊動作。

測試

隨便一個普通的 Java 類進行註冊到容器中:

public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context。register(FistBeanFactoryPostProcessor。class); context。refresh(); FistBeanFactoryPostProcessor postProcessor = (FistBeanFactoryPostProcessor) context。getBean(“fistBeanFactoryPostProcessor”); System。out。println(null != postProcessor); }

透過斷點除錯,省略中間其它過程說明,直接上核心程式碼:

BeanDefinitionReaderUtils。registerBeanDefinition(definitionHolder, this。registry);

@Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert。hasText(beanName, “Bean name must not be empty”); Assert。notNull(beanDefinition, “BeanDefinition must not be null”); if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition) beanDefinition)。validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition。getResourceDescription(), beanName, “Validation of bean definition failed”, ex); } } BeanDefinition existingDefinition = this。beanDefinitionMap。get(beanName); if (existingDefinition != null) { if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } else if (existingDefinition。getRole() < beanDefinition。getRole()) { // e。g。 was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (logger。isInfoEnabled()) { logger。info(“Overriding user-defined bean definition for bean ‘” + beanName + “’ with a framework-generated bean definition: replacing [” + existingDefinition + “] with [” + beanDefinition + “]”); } } else if (!beanDefinition。equals(existingDefinition)) { if (logger。isDebugEnabled()) { logger。debug(“Overriding bean definition for bean ‘” + beanName + “’ with a different definition: replacing [” + existingDefinition + “] with [” + beanDefinition + “]”); } } else { if (logger。isTraceEnabled()) { logger。trace(“Overriding bean definition for bean ‘” + beanName + “’ with an equivalent definition: replacing [” + existingDefinition + “] with [” + beanDefinition + “]”); } } this。beanDefinitionMap。put(beanName, beanDefinition); } else { if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this。beanDefinitionMap) { this。beanDefinitionMap。put(beanName, beanDefinition); List updatedDefinitions = new ArrayList<>(this。beanDefinitionNames。size() + 1); updatedDefinitions。addAll(this。beanDefinitionNames); updatedDefinitions。add(beanName); this。beanDefinitionNames = updatedDefinitions; removeManualSingletonName(beanName); } } else { // Still in startup registration phase this。beanDefinitionMap。put(beanName, beanDefinition); this。beanDefinitionNames。add(beanName); removeManualSingletonName(beanName); } this。frozenBeanDefinitionNames = null; } if (existingDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } }

超實用的 Spring 註解驅動開發技術

// 所有的 bean 註冊最終都是 put beanDefinitionMap 中private final Map beanDefinitionMap = new ConcurrentHashMap<>(256);// 註冊的 bean nameprivate volatile List beanDefinitionNames = new ArrayList<>(256);

2. 重新整理容器 refresh()

AbstractApplicationContext 是 ApplicationContextspring IOC 容器的基類,refresh 方法是 Spring 最核心的方法,搞清楚這個方法的執行過程,拓展原理基本一看就會。

Spring 容器建立之後,會呼叫它的 refresh 方法重新整理 Spring 應用的上下文。

Spring Boot 專案啟動 run 中也是呼叫 refresh() 重新整理上下文:

超實用的 Spring 註解驅動開發技術

超實用的 Spring 註解驅動開發技術

超實用的 Spring 註解驅動開發技術

超實用的 Spring 註解驅動開發技術

原始碼解析:

public void refresh() throws BeansException, IllegalStateException { synchronized (this。startupShutdownMonitor) { // Prepare this context for refreshing。 //前期準備;記錄了容器啟動時間;容器狀態;重新整理一些在此方法之前就可能已經存在的監聽器 prepareRefresh(); // Tell the subclass to refresh the internal bean factory。 //最終得到 DefaultListableBeanFactory,也就是在 this()方法中透過父類建構函式初始化的那個 bean factory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context。 //準備 bean factory,初始化工廠的一些標準固定的容器特性 //因為後邊一系列容器初始化操作,都是基於 beanFactory,所以前期準備得充足 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses。 //空方法,用於子類擴充套件功能 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context。 //例項化並執行之前已經註冊了的各種 BeanFactoryPostProcessor invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation。 //例項化 攔截 bean 建立的處理器 BeanPostProcessor; //這裡的註冊,是指把例項化的 BeanPostProcessor 存到 beanFactory 的某個 list 中 registerBeanPostProcessors(beanFactory); // Initialize message source for this context。 //初始化容器的 MessageSource 型別的 bean,MessageSource 用於解析訊息 initMessageSource(); // Initialize event multicaster for this context。 //初始化容器的事件廣播 //用於管理若干 ApplicationListener 物件,並向他們推送訊息 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses。 //空方法,在特定的子類中 初始化其他特殊 bean onRefresh(); // Check for listener beans and register them。 //註冊實現了 ApplicationListener 介面的監聽者 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons。 //例項化剩下的單例 bean,完成全部 bean 的例項化,除了懶載入的 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event。 //最後一步,完成此重新整理方法,釋出完成事件 finishRefresh(); } catch (BeansException ex) { if (logger。isWarnEnabled()) { logger。warn(“Exception encountered during context initialization - ” + “cancelling refresh attempt: ” + ex); } // Destroy already created singletons to avoid dangling resources。 destroyBeans(); // Reset ‘active’ flag。 cancelRefresh(ex); // Propagate exception to caller。 throw ex; } finally { // Reset common introspection caches in Spring‘s core, since we // might not ever need metadata for singleton beans anymore。。。 resetCommonCaches(); } }}

內部方法解析

總共分為 12 個重要過程,這裡挑選重點解析。

1. prepareRefresh

protected void prepareRefresh() { // Switch to active。 //容器啟動時刻 this。startupDate = System。currentTimeMillis(); //容器啟用狀態,預設沒有關閉 this。closed。set(false); //容器啟用狀態,預設啟用的 this。active。set(true); if (logger。isInfoEnabled()) { logger。info(“Refreshing ” + this); } // Initialize any placeholder property sources in the context environment。 //空方法 initPropertySources(); // Validate that all properties marked as required are resolvable: // see ConfigurablePropertyResolver#setRequiredProperties getEnvironment()。validateRequiredProperties(); // Store pre-refresh ApplicationListeners。。。 //執行 refresh 之前就已經註冊的 listeners 集合,如果沒有,就初始化集合; //除錯發現是 null 的 if (this。earlyApplicationListeners == null) { this。earlyApplicationListeners = new LinkedHashSet<>(this。applicationListeners); } else { // Reset local application listeners to pre-refresh state。 //如果不為空,重新設定到 applicationListeners 監聽器集合 this。applicationListeners。clear(); this。applicationListeners。addAll(this。earlyApplicationListeners); } // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available。。。 //事件集合初始化 this。earlyApplicationEvents = new LinkedHashSet<>();}

2. invokeBeanFactoryPostProcessors(beanFactory)

例項化並執行之前已經註冊了的各種 BeanFactoryPostProcessor,可用於拓展。

BeanFactoryPostProcessor

是 beanFactory 的後置處理器,也就是說當所有的 bean 定義已經儲存並載入到 beanFactory,但是卻沒有被例項化。那麼執行順序:beanFactory > BeanFactoryPostProcessor > bean , 也就是說初始化完 beanFactory 之後 BeanFactoryPostProcessor 才會被呼叫,因此 BeanFactoryPostProcessor 是在 bean 初始化之後才會被呼叫,使用場景:用於定製或者修改 BeanFactory 的內容。

BeanFactoryPostProcessor 原理如下。

1。 IOC 容器建立物件:

invokeBeanFactoryPostProcessors(beanFactory);

2。 先根據型別獲取各種 postProcessorNames:

String[] postProcessorNames = beanFactory。getBeanNamesForType(BeanFactoryPostProcessor。class, true, false);

分類儲存為各種 priorityOrderedPostProcessors、orderedPostProcessors、nonOrderedPostProcessors 的集合其實就是各種 BeanFactoryPostProcessor。

然後分別排序上一步的各種集合,按順序分別執行各種 BeanFactory 的後置處理器。

案例:實現 BeanFactoryPostProcessor 介面。

public interface BeanFactoryPostProcessor { /** * Modify the application context’s internal bean factory after its standard * initialization。 All bean definitions will have been loaded, but no beans * will have been instantiated yet。 This allows for overriding or adding * properties even to eager-initializing beans。 * @param beanFactory the bean factory used by the application context * @throws org。springframework。beans。BeansException in case of errors */ void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;}

public class FistBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { int beanDefinitionCount = beanFactory。getBeanDefinitionCount(); System。out。println(“容器中的 bean 數量:” + beanDefinitionCount); int beanPostProcessorCount = beanFactory。getBeanDefinitionCount(); System。out。println(“beanPostProcessorCount:” + beanPostProcessorCount); String[] beanDefinitionNames = beanFactory。getBeanDefinitionNames(); for (String beanName : beanDefinitionNames) { System。out。println(“beanDefinitionName:” + beanName); } System。out。println(“——————————————BeanFactoryPostProcessor is after——————————————————”); } public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(FistBeanFactoryPostProcessor。class); String[] beanDefinitionNames = context。getBeanDefinitionNames(); for (String beanName : beanDefinitionNames) { System。out。println(“beanName:” + beanName); } }}

輸出結果:

超實用的 Spring 註解驅動開發技術

3. postProcessBeanFactory(beanFactory)

空方法,用於子類擴充套件功能。

4. BeanDefinitionRegistryPostProcessor

在所有 bean 定義資訊將要被載入,bean 例項還未建立的;

優先於 BeanFactoryPostProcessor 執行;

利用 BeanDefinitionRegistryPostProcessor 給容器中再額外新增一些元件。

5. BeanFactoryPostProcessor 原理

IOC 建立物件

refresh() -> invokeBeanFactoryPostProcessors(beanFactory);

從容器中獲取到所有的 BeanDefinitionRegistryPostProcessor 元件。

String[] postProcessorNames = beanFactory。getBeanNamesForType(BeanDefinitionRegistryPostProcessor。class 。。);

invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry) -> 依次觸發所有的 postProcessBeanDefinitionRegistry() 方法 。

再來觸發 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory) -> postProcessBeanFactory() 方法 BeanFactoryPostProcessor。

之後從容器中找到 BeanFactoryPostProcessor 元件,然後依次觸發 postProcessBeanFactory() 方法。

案例:

public class FistBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { System。out。println(“FistBeanDefinitionRegistryPostProcessor。。。bean 的數量:”+beanDefinitionRegistry。getBeanDefinitionCount()); RootBeanDefinition definition = new RootBeanDefinition(FistBeanFactoryPostProcessor。class); beanDefinitionRegistry。registerBeanDefinition(“test”,definition); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { System。out。println(“FistBeanDefinitionRegistryPostProcessor。。。bean 的數量:”+configurableListableBeanFactory。getBeanDefinitionCount()); } public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(FistBeanDefinitionRegistryPostProcessor。class); String[] beanDefinitionNames = context。getBeanDefinitionNames(); for (String beanName : beanDefinitionNames) { System。out。println(“beanName:” + beanName); } }}

超實用的 Spring 註解驅動開發技術

6. registerListeners()

用於管理 ApplicationListener:

protected void registerListeners() { // Register statically specified listeners first。 for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster()。addApplicationListener(listener); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let post-processors apply to them! String[] listenerBeanNames = getBeanNamesForType(ApplicationListener。class, true, false); for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster()。addApplicationListenerBean(listenerBeanName); } // Publish early application events now that we finally have a multicaster。。。 //廣播事件到對應的監聽器; //earlyApplicationEvents 是在第一個方法 prepareRefresh()中初始化的 Set earlyEventsToProcess = this。earlyApplicationEvents; this。earlyApplicationEvents = null; if (earlyEventsToProcess != null) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster()。multicastEvent(earlyEvent); } }}

7. finishBeanFactoryInitialization(beanFactory)

例項化所有的 bean,除了懶載入的 bean。

8. finishRefresh()

釋出所有的事件:

protected void finishRefresh() { // Clear context-level resource caches (such as ASM metadata from scanning)。 clearResourceCaches(); // Initialize lifecycle processor for this context。 initLifecycleProcessor(); // Propagate refresh to lifecycle processor first。 //執行 LifecycleProcessor 的方法 getLifecycleProcessor()。onRefresh(); // Publish the final event。 //釋出完成事件給所有的監聽者 publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active。 LiveBeansView。registerApplicationContext(this);}

總結

原始碼執行過程詳解

prepareRefresh 準備重新整理容器

initPropertySources() 自定義屬性設定,空方法,留給子類繼承。

getEnvironment。validateRequiredProperties 首先獲取環境配置,然後校驗必需屬性。

this。earlyApplicationListeners = new LinkedHashSet<>(this。applicationListeners); 初始化事件監聽器。

this。earlyApplicationEvents = new LinkedHashSet<>(); 初始化早期事件。

obtainFreshBeanFactory 獲取元件工廠

refreshBeanFactory 新建一個元件工廠,型別為 DefaultListableBeanFactory,然後對這個元件工廠設定了一個序列化 ID。

getBeanFactory 返回剛剛建立的元件工廠。

prepareBeanFactory 對元件工廠做各種預處理設定

在元件工廠中設定類載入器、屬性解析器等。

在元件工廠中新增部分元件後置處理器,例如 ApplicationContextAwareProcessor、ApplicationListenerDetector。

在元件工廠中設定忽略自動注入的介面。

設定自動裝配規則。

在元件工廠中註冊一些元件,例如環境配置 ConfigurableEnvironment。

postProcessBeanFactory 元件工廠的後置處理工作

invokeBeanFactoryPostProcessors 執行元件工廠後置處理器

這一步是在元件工廠的標準初始化(1~4)之後進行的,主要是執行 BeanFactoryPostProcessor 及其子介面的。

BeanFactoryPostProcessor 的子介面主要是指 BeanDefinitionRegistryPostProcessor,可以向容器中註冊新的元件,這個介面的特點是有兩個方法,一個是自身的 postProcessBeanDefinitionRegistry,另一個繼承自 BeanFactoryPostProcessor 的 postProcessBeanFactory,從原始碼可以看出,Spring 會先執行 BeanDefinitionRegistryPostProcessor 型別的元件的自身方法,然後執行其繼承方法,最後才呼叫非 BeanDefinitionRegistryPostProcessor 的 BeanFactoryPostProcessor 的後置處理方法。

從容器器中獲取 BeanDefinitionRegistryPostProcessor 型別的元件。

將 BeanDefinitionRegistryPostProcessor 型別的元件按照順序分類並排序,即是否實現了 PriorityOrdered、Ordered 介面。

依次執行實現了 PriorityOrdered 介面的、實現了 Ordered 介面的、沒有實現任何順序介面的元件的 postProcessBeanDefinitionRegistry 方法。

執行所有 BeanDefinitionRegistryPostProcessor 元件的 postProcessBeanFactory 方法。

從容器中獲取其他的 BeanFactoryPostProcessor 型別的元件,即不是 BeanDefinitionRegistryPostProcessor 型別的。

剩下的步驟跟上面類似,就是先按照實現的順序介面分類,在每個類別下排序,然後依次執行它們的 postProcessBeanFactory 方法。

registerBeanPostProcessors 註冊元件後置處理器

這種處理器用於攔截 bean 的建立過程。beanPostProcessor 有很多子介面,每種子介面的執行時機各有不同。

DestructionAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor

MergedBeanDefinitionPostProcessor

SmartInstantiationAwareBeanPostProcessor

1。 獲取所有的 beanPostProcessor 的元件名。

2。 將所有的元件按優先順序分為三類:

實現了 PriorityOrdered 介面的列表 priorityOrderedPostProcessors

實現了 Ordered 介面的列表 orderedPostProcessors

沒有實現任何順序介面的列表 nonOrderedPostProcessors

還有一種特殊情況,凡是 MergedBeanDefinitionPostProcessor 型別的,都放在 internalPostProcessors 中。

3。 註冊 priorityOrderedPostProcessors。

4。 註冊 orderedPostProcessors。

5。 註冊 nonOrderedPostProcessors。

6。 註冊 internalPostProcessors。

7。 註冊 ApplicationListenerDetector,它的作用是在元件初始化之後判斷其是否為 ApplicationListner 型別,如果是,則將其新增進容器的監聽器集合。

initMessageSource 初始化訊息源元件

用於訊息繫結、訊息解析等功能,並且提供國際化解決方案。

獲取 beanFactory。

判斷 beanFactory 中是否包含 id 為 messageSource 的元件。

如果已存在,則賦值給容器的 messageSource 屬性,這種情況是我們自己在容器中註冊了這個元件。

如果不存在,則新建一個 DelegatingMessageSource,並賦值給容器的 messageSource 屬性,然後在 beanFactory 中註冊這個新元件,並設定其 id 為 messageSource。

initApplicationEventMulticaster 初始化事件廣播器

獲取 beanFactory。

判斷 beanFactory 中是否存在 id 為 applicationEventMulticaster 的元件

如果已存在,則賦值給容器的 applicationEventMulticaster 屬性,這種情況是我們自己在容器中註冊了這個元件。

如果不存在,則新建一個 SimpleApplicationEventMulticaster,並賦值給容器的 applicationEventMulticaster 屬性,然後在 beanFactory 中註冊這個新元件, 並設定其 id 為 applicationEventMulticaster。

onRefresh

留給子類繼承的,我們可以自定義子容器,在重寫方法中做一些我們想要的操作。

registerListeners 註冊事件監聽器

獲取容器的屬性 applicationListeners,這是一個事件監聽器的集合,將集合中的每個元素都新增進事件廣播器 getApplicationEventMulticaster()。addApplicationListener(listener);。

從容器中獲取所有 ApplicationListener 型別的元件,將這些元件新增進事件廣播器。

派發之前步驟產生的事件。

finishBeanFactoryInitialization 完成剩下的單例項 bean 的初始化

進入 DefaultListableBeanFactory。preInstantiateSingletons 方法,獲取容器中所有的元件 id 列表。

獲取容器中的所有 Bean,依次進行初始化和建立物件。

Bean 不是抽象的,是單例項的,是非懶載入。

判斷是否是 FactoryBean;是否是實現 FactoryBean 介面的 Bean;如果是就用工廠 bean 來建立及 FacBean 中的 getObject 同 SpringIOC 中的二(3)。如果不是工廠 Bean。利用 getBean(beanName) 建立物件。

getBean(beanName); ioc。getBean();

AbstractBeanFactory。doGetBean(name, null, null, false);

先獲取快取中儲存的單例項 Bean。如果能獲取到說明這個 Bean 之前被建立過(所有建立過的單例項 Bean 都會被快取起來),Object sharedInstance = getSingleton(beanName); 快取到 DefaultSingletonBeanRegistry 類的 singletonObjects 單例物件儲存的 Map 一級快取。

快取中獲取不到,開始 Bean 的建立物件流程。標記當前 bean 已經被建立:

markBeanAsCreated(beanName);

獲取 Bean 的定義資訊:

RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName)

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

String[] dependsOn = mbd。getDependsOn()

啟動單例項 Bean 的建立流程如下:

AbstractAutowireCapableBeanFactory。createBean(beanName, mbd, args);

讓 BeanPostProcessor 先攔截返回代理物件:

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

InstantiationAwareBeanPostProcessor 提前執行,先觸發 postProcessBeforeInstantiation(),如果有返回值,觸發 postProcessAfterInitialization()。

如果前面的 InstantiationAwareBeanPostProcessor 沒有返回代理物件,呼叫 AbstractAutowireCapableBeanFactory。doCreateBean 建立 Bean。

建立 Bean 例項:

createBeanInstance(beanName, mbd, args);

利用工廠方法或者物件的構造器創建出 Bean 例項。

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

呼叫 MergedBeanDefinitionPostProcessor 的 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 介面方法:

invokeAwareMethods(beanName, bean);

執行 xxxAware 介面的方法 BeanNameAware\BeanClassLoaderAware\BeanFactoryAware。

執行後置處理器初始化之前:

applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);BeanPostProcessor。postProcessBeforeInitialization();

執行初始化方法:

invokeInitMethods(beanName, wrappedBean, mbd);

是否是 InitializingBean 介面的實現,執行介面規定的初始化,是否自定義初始化方法。

執行後置處理器初始化之後,applyBeanPostProcessorsAfterInitialization 也就是 BeanPostProcessor。postProcessAfterInitialization()。

註冊 Bean 的銷燬方法:

registerDisposableBeanIfNecessary(beanName, bean, mbd);

將建立的 Bean 新增到快取中 singletonObjects。

finishRefresh 完成容器重新整理

初始化生命週期處理器(LifecycleProcessor),先從 BeanFactory 中按型別獲取,如果沒有就新建一個 DefaultLifecycleProcessor,並註冊進 BeanFactory。

獲取上一步註冊的生命週期處理器,回撥其 onRefresh 方法。

釋出容器重新整理事件,即 ContextRefreshedEvent。

流程圖詳解

超實用的 Spring 註解驅動開發技術

簡述

Spring 容器在啟動的時候,先會儲存所有註冊進來的 Bean 的定義資訊:

xml 註冊 bean:

註解註冊 Bean:@Service、@Component、@Bean、xxx

Spring 容器會合適的時機建立這些 Bean:

用到這個 bean 的時候,利用 getBean 建立 bean,建立好以後儲存在容器中。

統一建立剩下所有的 bean 的時候 finishBeanFactoryInitialization()。

後置處理器 BeanPostProcessor

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

AutowiredAnnotationBeanPostProcessor:處理自動注入

AnnotationAwareAspectJAutoProxyCreator:來做 AOP 功能

。。。。

增強的功能註解:AsyncAnnotationBeanPostProcessor

。。。。

事件驅動模型

ApplicationListener:事件監聽

ApplicationEventMulticaster:事件派發