前言
Spring是什麼?
Spring發展至今,已經不是簡單的Spring Framework,它包括Spring Data、Spring Boot、Spring Cloud等等組成
不過這裡我們僅討論Spring Framework,重點討論Spring的啟動過程及擴充應用
Spring啟動
監聽器啟動
web.xml配置
Spring通過監聽器啟動是最常見的方式(後續文章會補上其它啟動方式,如用SpringBoot啟動等)ContextLoaderListener實現了ServletContextListener,會在web容器啟動的時候呼叫 進入initWebApplicationContext() 這裡只挑重點方法講 this.context = createWebApplicationContext(servletContext);預設會建立一個XmlWebApplicationContext
而後進入configureAndRefreshWebApplicationContext(cwac, servletContext) 獲取所有需要初始化的配置檔案sc.getInitParameter(CONFIG_LOCATION_PARAM) 也就是上面一開始配置的context-param標籤 最後執行refresh
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資訊都儲存起來,會在後邊一個一個去例項化
最終進入 reader.loadBeanDefinitions(configLocation)方法很深,我看了下,程式碼很深,大致的內容:
根據件用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)
這裡沒仔細看
執行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)