前言
Spring是什麼?
Spring發展至今,已經不是簡單的Spring Framework,它包括Spring Data、Spring Boot、Spring Cloud等等組成
不過這裡我們僅討論Spring Framework,重點討論Spring的啟動過程及擴充應用
Spring啟動
監聽器啟動
web.xml配置

ContextLoaderListener實現了ServletContextListener,會在web容器啟動的時候呼叫



而後進入configureAndRefreshWebApplicationContext(cwac, servletContext)

Spring容器建立過程
refresh()
刪減了一些無關緊要的程式碼
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory)
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
}
}
複製程式碼
prepareRefresh()
容器refresh預準備工作 AbstractApplicationContext

-
initPropertySources() AbstractApplicationContext子類自定義屬性設定的方法
-
getEnvironment().validateRequiredProperties() 校驗設定屬性
-
this.earlyApplicationEvents = new LinkedHashSet<>() 儲存容器早期的事件
obtainFreshBeanFactory()
獲取工廠

- refreshBeanFactory()

BeanDefinition是工廠中非常重要的屬性,它將所有需要spring管理的bean資訊都儲存起來,會在後邊一個一個去例項化
最終進入

根據件用xmlReader去讀取一個個配置檔案 最終呼叫
this.beanDefinitionMap.put(beanName, beanDefinition)
refreshBeanFactory執行完進入getBeanFactory()
直接返回改beanFactory 方法結束
prepareBeanFactory(beanFactory)

-
在工廠設定類載入器、表示式解析器
-
給工廠新增ApplicationContextAwareProcessor(processor先不解釋有什麼意思 後續會說明)
-
設定需要忽略的自動裝配的介面(EnvironmentAware、ApplicationContextAware等Aware)
-
給工廠新增 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this))
接著上面方法


- environment(ConfigurableEnvironment)
- systemProperties(Map<String, Object>)
- systemEnvironment(Map<String, Object>)
postProcessBeanFactory(beanFactory)
BeanFactory準備工作完成後 後置處理
空方法 子類自定義屬性設定的方法
這裡web環境 用的工廠是AbstractRefreshableWebApplicationContext
記住這裡只是web端擴充才有的實現

WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext)
新增了幾個scope
spring本身只有singleton和prototype兩個,web環境加上了request、session、globalSession
invokeBeanFactoryPostProcessors(beanFactory)
這裡沒仔細看

BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
他們的關係:BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor





-
先獲取所有的BeanDefinitionRegistryPostProcessor
-
依次執行實現了PriorityOrdered、Ordered介面和沒有實現它們的 processor postProcessor.postProcessBeanDefinitionRegistry(registry)
在這裡我debug發現 spring內部有一個ConfigurationClassPostProcessor
它的作用是負責解析處理所有@Configuration標籤類,並將Bean定義(包括其它processor)註冊到BeanFactory中。
這裡註冊完之後 再次獲取所有BeanDefinitionRegistryPostProcessor,按順序執行invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)
重點:其它的BeanDefinitionRegistryPostProcessor就是Spring提供給我們註冊bean的通道 -
再執行postProcessor.postProcessBeanFactory(beanFactory)
-
獲取所有的BeanFactoryPostProcessor
-
分類執行 執行過的不再執行

實踐出真知 這裡是用SpringBoot簡單搭起的一個demo,跟上面不一樣,不過不影響測試結果




- 先執行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry
- 再執行BeanDefinitionRegistryPostProcessor的postProcessBeanFactory
- 最後執行BeanFactoryPostProcessor的postProcessBeanFactory
registerBeanPostProcessors(beanFactory)
註冊Bean的後置處理器(跟上面的FactoryPostProcessor不一樣)
Bean的生命週期: Bean建立--初始化--銷燬
不同BeanPostProcessor功能都不一樣
BeanPostProcessor的實現子介面:
DestructionAwareBeanPostProcessor InstantiationAwareBeanPostProcessor MergedBeanDefinitionPostProcessor SmartInstantiationAwareBeanPostProcessor
BeanPostProcessor


獲取所有BeanPostProcessor 依次註冊了PriorityOrdered、Ordered介面、沒有實現它們的、MergedBeanDefinitionPostProcessor
註冊呼叫的是

註冊ApplicationListenerDetector :在bean初始化後 檢查如果是listener的話 執行applicationContext.addApplicationListener
initMessageSource()
初始化MessageSource元件(做國際化、訊息繫結、訊息解析)

- 獲取BeanFactory
- 檢視容器是否有messageSource的元件
-
有->this.applicationEventMulticaster beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class)
-
沒有->new DelegatingMessageSource() 註冊一個MessageSource元件
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource)
initApplicationEventMulticaster()
初始化事件派發器

- 獲取BeanFactory
- 檢視容器是否有applicationEventMulticaster的元件
-
有->this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class)
-
沒有->new SimpleApplicationEventMulticaster() beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster)
這個派發器在後續很有用
onRefresh()
子類自定義的方法 web環境下直接進入一個空方法
還不確定什麼環境下會有執行 歡迎聯絡交流~
registerListeners()

- 獲取所有ApplicationListener
- getApplicationEventMulticaster().addApplicationListenerBean
這裡拿到的派發器就是剛才註冊的
finishBeanFactoryInitialization(beanFactory)
較為複雜,單獨作為一篇
finishRefresh()

- 初始化和生命週期有關的後置處理器 initLifecycleProcessor()
- LifecycleProcessor:
- void onRefresh();
呼叫生命週期處理器的onRefresh方法,這個方法會找出Spring容器中實現了SmartLifecycle介面的類並進行start方法的呼叫
- 釋出ContextRefreshedEvent事件告知對應的ApplicationListener進行響應的操作
publishEvent(new ContextRefreshedEvent(this)) - 呼叫LiveBeansView的registerApplicationContext方法:如果設定了JMX相關的屬性,則就呼叫該方法 LiveBeansView.registerApplicationContext(this)