淺嘗Spring註解開發_Spring容器建立概述
淺嘗Spring註解開發,基於Spring 4.3.12
概述Spring容器建立的過程,包括12個方法的執行
淺嘗Spring註解開發_自定義註冊元件、屬性賦值、自動裝配
淺嘗Spring註解開發_Bean生命週期及執行過程
淺嘗Spring註解開發_AOP原理及完整過程分析(原始碼)
淺嘗Spring註解開發_宣告式事務及原理
淺嘗Spring註解開發_簡單理解BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor、ApplicationListener
Spring註解開發_Spring容器建立概述
概述12個方法
//獲取ioc容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfPropertyValues.class);
/**
* 建立一個新的AnnotationConfigApplicationContext,派生bean定義
* 從給定的帶註釋的類,並自動重新整理上下文。
* @param 類一個或多個帶註釋的類
* e.g. {@link Configuration @Configuration} classes
*/
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 為重新整理準備此上下文。
prepareRefresh();
// 告訴子類重新整理內部bean工廠。
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 準備在此上下文中使用bean工廠。
prepareBeanFactory(beanFactory);
try {
// 允許在上下文子類中對bean工廠進行後處理。
postProcessBeanFactory(beanFactory);
// 呼叫在上下文中註冊為bean的工廠處理器。
invokeBeanFactoryPostProcessors(beanFactory);
// 註冊攔截bean建立的bean處理器。
registerBeanPostProcessors(beanFactory);
// 初始化此上下文的訊息源。
initMessageSource();
// 為此上下文初始化事件多播。
initApplicationEventMulticaster();
// 在特定的上下文子類中初始化其他特殊bean。
onRefresh();
// 檢查監聽器bean並註冊它們。
registerListeners();
// 例項化所有剩餘的(非lazy-init)單例。
finishBeanFactoryInitialization(beanFactory);
// 最後一步:釋出相應的事件。
finishRefresh();
}
//...
BeanFactory預處理
BeanFactory的建立及預準備工作
- BeanFactory 的作用是負責 bean 的建立、依賴注入和初始化,bean 的各項特徵由 BeanDefinition 定義
- BeanDefinition 作為 bean 的設計藍圖,規定了 bean 的特徵,如單例多例、依賴關係、初始銷燬方法等
- BeanDefinition 的來源有多種多樣,可以是通過 xml 獲得、配置類獲得、元件掃描獲得,也可以是程式設計新增
- 所有的 BeanDefinition 會存入 BeanFactory 中的 beanDefinitionMap 集合
1、this()
- 先呼叫父類構造器
- 宣告兩個類,通過讀取註解或者掃描類路徑讀取
BeanDefinition
- 初始化了DefaultListableBeanFactory:基於bean定義後設資料的成熟bean工廠,可通過後處理器進行擴充套件,內部定義了
BeanDefinition
的Map
屬性名beanDefinitionMap
,可以操作bean
- 註冊了多個(6個)預設的後置處理器
2、register(annotatedClasses)
- 校驗傳入的
JavaConfig.class
配置類的註解(是否需要忽略) - 處理通用註解
- 封裝為
BeanDefinitionHolder
後,註冊到容器中 - 相當於將JavaConfig配置類作為一個Bean註冊到容器中
3、Spring容器的refresh()
:建立重新整理
prepareRefresh()
:重新整理前的預處理initPropertySources()[初始化屬性源]
:初始化一些屬性設定,空方法,留給子類自定義個性化的屬性設定方法getEnvironment().validateRequiredProperties()
:檢驗屬性的合法等earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>()
:儲存容器中的一些早期的事件,一旦多播機可用就會發布
obtainFreshBeanFactory()(//告訴子類重新整理內部Bean工廠)
:獲取新鮮的BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
類註釋://大多數可列出的bean工廠要實現的配置介面。 除了 {@link ConfigurableBeanFactory} 之外,它還提供了以下工具: 分析和修改 bean 定義,並預例項化單例。
refreshBeanFactory()
:重新整理[建立]BeanFactory
- 建立了一個
this.beanFactory = new DefaultListableBeanFactory()
。補充:這個方法在建立AnnotationConfigApplicationContext
的父類GenericApplicationContext
的無參構造時呼叫了,註釋是//建立一個新的 GenericApplicationContext
- 設定id
- 建立了一個
getBeanFactory()
:返回剛才GenericApplicationContext
建立的BeanFactory
物件- 將建立的
BeanFactory
[型別:DefaultListableBeanFactory
]返回
prepareBeanFactory(beanFactory)
:BeanFactory
的預準備工作(BeanFactory
進行一些設定)- 設定
BeanFactory
的類載入器、支援表示式解析器... - 新增部分
BeanPostProcessor
[型別:ApplicationContextAwareProcessor
] - 設定忽略的自動裝配的介面
EnvironmentAware
、EmbeddedValueResolverAware
、xxx...
- 註冊可以解析的自動裝配;我們能直接在任何元件中自動注入:
BeanFactory
、ResourceLoader
、ApplicationEventPublisher
、ApplicationContext...
- 新增
BeanPostProcessor
[型別:ApplicationListenerDetector
],將用於檢測內部 bean 的早期後處理器註冊為ApplicationListener
- 新增編譯時的
AspectJ
- 給
BeanFactory
中註冊一些能用的元件;ConfigurableEnvironment environment
:application
上下文環境Map<String, Object> systemProperties
:系統屬性Map<String, Object> systemEnvironment
:系統環境變數
- 設定
postProcessBeanFactory(beanFactory)
:BeanFactory
準備工作完成後進行的後置處理工作- 子類通過重寫這個方法來在
BeanFactory
建立並預準備完成以後做進一步的設定
- 子類通過重寫這個方法來在
執行BeanFactoryPostProcessor
BeanFactoryPostProcessor是beanFactory的後置處理器
BeanFactoryPostProcessor是beanFactory的後置處理器,在BeanFactory標準初始化之後呼叫,來定製和修改BeanFactory的內容,所有的bean定義已經儲存載入到beanFactory,但是bean的例項還未建立
執行BeanFactoryPostProcessor分兩步,先執行BeanDefinitionRegistryPostProcessor,後執行BeanFactoryPostProcessor
-
invokeBeanFactoryPostProcessors(beanFactory)
:執行BeanFactoryPostProcessor
的方法。BeanFactoryPostProcessor
:BeanFactory
的後置處理器。在BeanFactory
標準初始化(以上4步)之後執行的,兩個介面:BeanFactoryPostProcessor
、BeanDefinitionRegistryPostProcessor
-
執行
BeanFactoryPostProcessor
的方法-
先執行
BeanDefinitionRegistryPostProcessor
-
獲取所有的
BeanDefinitionRegistryPostProcessor
-
看先執行實現了
PriorityOrdered
優先順序介面的BeanDefinitionRegistryPostProcessor
postProcessor.postProcessBeanDefinitionRegistry(registry)
-
再執行實現了
Ordered
順序介面的BeanDefinitionRegistryPostProcessor
postProcessor.postProcessBeanDefinitionRegistry(registry)
-
最後執行沒有實現任何優先順序或者是順序介面的
BeanDefinitionRegistryPostProcessors
postProcessor.postProcessBeanDefinitionRegistry(registry)
-
-
再執行
BeanFactoryPostProcessor
的方法-
獲取所有的
BeanFactoryPostProcessor
-
看先執行實現了
PriorityOrdered
優先順序介面的BeanFactoryPostProcessor
postProcessor.postProcessBeanFactory()
-
再執行實現了
Ordered
順序介面的BeanFactoryPostProcessor
postProcessor.postProcessBeanFactory()
-
最後執行沒有實現任何優先順序或者是順序介面的
BeanFactoryPostProcessor
postProcessor.postProcessBeanFactory()
-
-
-
註冊BeanPostProcessor
按照優先順序註冊後置處理器,不執行
-
registerBeanPostProcessors(beanFactory)
:註冊BeanPostProcessor
(Bean的後置處理器)攔截Bean的建立不同介面型別的
BeanPostProcessor
,在Bean建立前後的執行時機是不一樣的-
BeanPostProcessor
後置處理器 -
DestructionAwareBeanPostProcessor
銷燬感知後置處理器 -
InstantiationAwareBeanPostProcessor
例項化感知後置處理器 -
SmartInstantiationAwareBeanPostProcessor
智慧例項化感知後置處理器 -
MergedBeanDefinitionPostProcessor[internalPostProcessors]
合併Bean定義資訊後置處理器
-
獲取所有的
BeanPostProcessor
,後置處理器都預設可以通過PriorityOrdered
、Ordered
介面來執行優先順序 -
先註冊
PriorityOrdered
優先順序介面的BeanPostProcessor
把每一個
BeanPostProcessor
新增到BeanFactory
中,beanFactory.addBeanPostProcessor(postProcessor)
-
再註冊
Ordered
介面的 -
最後註冊沒有實現任何優先順序介面的
-
最終註冊
MergedBeanDefinitionPostProcessor
-
註冊一個
ApplicationListenerDetector
,來在Bean建立完成後檢查是否是ApplicationListener
,如果是就新增元件applicationContext.addApplicationListener((ApplicationListener<?>) bean)
-
初始化MessageSource
國際化
-
initMessageSource()
:初始化MessageSource
元件(做國際化功能;訊息繫結,訊息解析)-
獲取
BeanFactory
-
看容器中是否有id為
messageSource
的,型別是MessageSource
的元件,如果有賦值給messageSource
,如果沒有自己建立一個DelegatingMessageSource
MessageSource
:取出國際化配置檔案中的某個key的值;能按照區域資訊獲取 -
把建立好的
MessageSource
註冊在容器中,以後獲取國際化配置檔案的值的時候,可以自動注入MessageSource
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource)
MessageSource.getMessage(String code, Object[] args, String defaultMessage, Locale locale)
-
初始化事件派發器、監聽器
-
initApplicationEventMulticaster()
:初始化事件派發器- 獲取
BeanFactory
- 從
BeanFactory
中獲取applicationEventMulticaster
的ApplicationEventMulticaster
- 如果上一步沒有配置,就建立一個
SimpleApplicationEventMulticaster
- 將建立的
ApplicationEventMulticaster
新增到BeanFactory
中,以後其他元件直接自動注入
- 獲取
-
onRefresh()
:留給子容器(子類)- 子類重寫這個方法,在容器重新整理的時候可以自定義邏輯;
-
registerListeners()
:給容器中將所有專案裡面的ApplicationListener
註冊進來;-
從容器中拿到所有的
ApplicationListener
-
將每個監聽器新增到事件派發器中
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName)
-
派發之前步驟產生的事件
-
建立Bean準備、完成
有代理物件就用,沒有就建立,然後在初始化前後準備各種後置處理器,建立完成後放入各種Map
-
finishBeanFactoryInitialization(beanFactory)
:初始化所有剩下的單例項bean-
beanFactory.preInstantiateSingletons()
:初始化剩下的單例項bean-
獲取容器中的所有Bean,依次進行初始化和建立物件
-
獲取Bean的定義資訊:
RootBeanDefinition
-
判斷Bean不是抽象的,是單例項的,不是懶載入
-
判斷是否是
FactoryBean
,是否是實現FactoryBean
介面的Bean -
如果不是工廠Bean。利用
getBean(beanName)
:建立物件-
這個
getBean(beanName)
就是平時測試類中用到的ioc.getBean()
-
doGetBean(name, null, null, false)
-
先獲取快取中儲存的單例項Bean。
this.singletonObjects.get(beanName)
,如果能獲取到說明這個Bean之前被建立過(所有建立過的單例項Bean都會被快取起來)可以從
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256)
屬性獲取到 -
快取中獲取不到,開始Bean的建立物件流程,使用
BeanFactory
-
標記當前bean已經被建立
markBeanAsCreated(beanName)
-
獲取Bean的定義資訊
-
【獲取當前Bean依賴的其他Bean,
mbd.getDependsOn()
,如果有按照就getBean()把依賴的Bean先建立出來】 -
啟動單例項Bean的建立流程
-
進入匿名類的
createBean(beanName, mbd, args)
方法(可以打斷點進入) -
Object bean = resolveBeforeInstantiation(beanName, mbdToUse)[給 BeanPostProcessors 一個返回代理而不是目標 Bean 例項的機會]
:讓BeanPostProcessor
先攔截返回代理物件【
InstantiationAwareBeanPostProcessor
提前執行,就是在AOP中先於BeanPostProcessor
執行的那個元件】- 先觸發:
postProcessBeforeInstantiation()例項化前的後處理
- 如果有返回值,觸發:
postProcessAfterInitialization()初始化後的後處理
- 先觸發:
-
如果前面的
InstantiationAwareBeanPostProcessor
沒有返回代理物件,呼叫第4步建立Bean -
Object beanInstance = doCreateBean(beanName, mbdToUse, args)
:建立Bean-
【建立Bean例項】:
createBeanInstance(beanName, mbd, args)
利用工廠方法或者物件的構造器建立出Bean例項
-
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)[允許後處理器修改合併的 Bean 定義。]
呼叫
MergedBeanDefinitionPostProcessor
的postProcessMergedBeanDefinition(mbd, beanType, beanName)
-
【Bean屬性賦值】
populateBean(beanName, mbd, instanceWrapper)
賦值之前:
-
拿到
InstantiationAwareBeanPostProcessor
後置處理器:postProcessAfterInstantiation()
例項化後的後處理(對應上面(8.2)) -
拿到
InstantiationAwareBeanPostProcessor
後置處理器:ibp.postProcessPropertyValues()
後處理屬性值
開始賦值:
-
應用Bean屬性的值;為屬性利用setter方法等進行賦值:
applyPropertyValues(beanName, mbd, bw, pvs)
-
-
【Bean初始化】
initializeBean(beanName, exposedObject, mbd)
:-
【執行Aware介面方法】
invokeAwareMethods(beanName, bean)
:執行xxxAware
介面的方法,如BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
-
【在初始化之前應用 BeanPostProcessors】
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)
BeanPostProcessor.postProcessBeforeInitialization()
-
【執行初始化方法】
invokeInitMethods(beanName, wrappedBean, mbd)
- 是否是
InitializingBean
介面的實現;執行介面規定的初始化 - 是否自定義初始化方法
- 是否是
-
【在初始化之後應用 BeanPostProcessors】
applyBeanPostProcessorsAfterInitialization
BeanPostProcessor.postProcessAfterInitialization()
-
-
註冊Bean的銷燬方法
-
-
將建立的Bean新增到快取中
singletonObjects
-
-
-
-
-
ioc容器就是這些Map,很多的Map裡面儲存了單例項Bean,環境資訊...
所有Bean都利用getBean建立完成以後:檢查所有的Bean是否是SmartInitializingSingleton[智慧初始化單例]
介面的,如果是,就執行afterSingletonsInstantiated()在單例例項化之後
容器建立完成
-
finishRefresh()
:完成BeanFactory
的初始化建立工作,IOC容器就建立完成-
initLifecycleProcessor()
:初始化和生命週期有關的後置處理器:LifecycleProcessor
-
預設從容器中找是否有
lifecycleProcessor
的元件【LifecycleProcessor
】; -
如果沒有
new DefaultLifecycleProcessor()
; -
加入到容器
onRefresh()
寫一個
LifecycleProcessor
的實現類,可以在BeanFactory
的生命週期onRefresh()
、onClose()
處攔截
-
-
getLifecycleProcessor().onRefresh()
拿到前面定義的生命週期處理器(
BeanFactory
),回撥onRefresh()
-
publishEvent(new ContextRefreshedEvent(this))
:釋出容器重新整理完成事件 -
LiveBeansView.registerApplicationContext(this)
-