Spring啓動過程——源碼分析

前言

Spring是什麼?
Spring發展至今,已經不是簡單的Spring Framework,它包括Spring Data、Spring Boot、Spring Cloud等等組成
不過這裏咱們僅討論Spring Framework,重點討論Spring的啓動過程及拓展應用java

Spring啓動

監聽器啓動

web.xml配置web

Spring經過監聽器啓動是最多見的方式(後續文章會補上其它啓動方式,如用SpringBoot啓動等)
ContextLoaderListener實現了ServletContextListener,會在web容器啓動的時候調用

進入initWebApplicationContext()
這裏只挑重點方法講 this.context = createWebApplicationContext(servletContext);默認會建立一個XmlWebApplicationContext
然後進入configureAndRefreshWebApplicationContext(cwac, servletContext)

獲取全部須要初始化的配置文件sc.getInitParameter(CONFIG_LOCATION_PARAM) 也就是上面一開始配置的context-param標籤 最後執行refresh

Spring容器建立過程

refresh()
刪減了一些可有可無的代碼spring

@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預準備工做 AbstractApplicationContextsession

  • initPropertySources() AbstractApplicationContext子類自定義屬性設置的方法app

  • getEnvironment().validateRequiredProperties() 校驗設置屬性ide

  • this.earlyApplicationEvents = new LinkedHashSet<>() 保存容器早期的事件post

obtainFreshBeanFactory()

獲取工廠測試

  • refreshBeanFactory()

重點講下 loadBeanDefinitions(beanFactory);
BeanDefinition是工廠中很是重要的屬性,它將全部須要spring管理的bean信息都存儲起來,會在後邊一個一個去實例化
最終進入

reader.loadBeanDefinitions(configLocation)方法很深,我看了下,代碼很深,大體的內容:
根據件用xmlReader去讀取一個個配置文件 最終調用
this.beanDefinitionMap.put(beanName, beanDefinition)

refreshBeanFactory執行完進入getBeanFactory()
直接返回改beanFactory 方法結束ui

prepareBeanFactory(beanFactory)

從上往下四個框框做用分別是

  • 在工廠設置類加載器、表達式解析器this

  • 給工廠添加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端拓展才有的實現

這裏先添加了一個ServletContextAwareProcessor和設置須要忽略的自動裝配的接口
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext)
添加了幾個scope

spring自己只有singleton和prototype兩個,web環境加上了request、session、globalSession

invokeBeanFactoryPostProcessors(beanFactory)

這裏沒仔細看

執行BeanFactory後置處理器 執行這兩種處理器
BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
他們的關係:BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor

總的來講

  1. 先獲取全部的BeanDefinitionRegistryPostProcessor

  2. 依次執行實現了PriorityOrdered、Ordered接口和沒有實現它們的 processor postProcessor.postProcessBeanDefinitionRegistry(registry)
    在這裏我debug發現 spring內部有一個ConfigurationClassPostProcessor
    它的做用是負責解析處理全部@Configuration標籤類,並將Bean定義(包括其它processor)註冊到BeanFactory中
    這裏註冊完以後 再次獲取全部BeanDefinitionRegistryPostProcessor,按順序執行 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)
    重點:其它的BeanDefinitionRegistryPostProcessor就是Spring提供給咱們註冊bean的通道

  3. 再執行postProcessor.postProcessBeanFactory(beanFactory)

  4. 獲取全部的BeanFactoryPostProcessor

  5. 分類執行 執行過的再也不執行

6. 依次執行實現了PriorityOrdered、Ordered接口和沒有實現它們的 processor postProcessor.postProcessBeanFactory(beanFactory)

實踐出真知 這裏是用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組件(作國際化、消息綁定、消息解析)

  1. 獲取BeanFactory
  2. 查看容器是否有messageSource的組件
  • 有->this.applicationEventMulticaster beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class)

  • 沒有->new DelegatingMessageSource() 註冊一個MessageSource組件
    beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource)

initApplicationEventMulticaster()

初始化事件派發器

和上面實現差很少

  1. 獲取BeanFactory
  2. 查看容器是否有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()

  1. 獲取全部ApplicationListener
  2. getApplicationEventMulticaster().addApplicationListenerBean
    這裏拿到的派發器就是剛纔註冊的

finishBeanFactoryInitialization(beanFactory)

較爲複雜,單獨做爲一篇

finishRefresh()

  1. 初始化和生命週期有關的後置處理器 initLifecycleProcessor()
  • LifecycleProcessor:
  • void onRefresh();
    調用生命週期處理器的onRefresh方法,這個方法會找出Spring容器中實現了SmartLifecycle接口的類並進行start方法的調用
  1. 發佈ContextRefreshedEvent事件告知對應的ApplicationListener進行響應的操做
    publishEvent(new ContextRefreshedEvent(this))
  2. 調用LiveBeansView的registerApplicationContext方法:若是設置了JMX相關的屬性,則就調用該方法 LiveBeansView.registerApplicationContext(this)
相關文章
相關標籤/搜索