首先看下,官方在代碼中給出的註釋:css
The root interface for accessing a Spring bean container.This is the basic client view of a bean container。java
是接觸全部Spring bean容器的根接口,這個接口被持有大量bean定義的對象實現。spring
從其接口中定義的方法便可看出,其爲bean容器的真正含義。數據庫
ListableBeanFactory 繼承了 BeanFactory,爲其提供了枚舉全部 beans 的方法:app
而 ApplicationContext 類經過對該接口的擴展,提供了爲application提供配置的擴展接口。ide
根據官方給出的註釋,其總共功能有如下幾點:post
這些能力主要經過繼承各類接口得到,其自身接口主要擴展的重要方法主要有一個:性能
1@Nullable
2ApplicationContext getParent();
複製代碼
在 SpringBoot 中,context 有其繼承體系:每一個不一樣的 servlet 都有本身獨立的 context,而整個 application 有一個根 context,這個 context 是全部 servlet 所共享的。ui
因此此處提供了得到父 context 的能力。this
所有或者絕大多數 application 的context都會實現或者繼承該接口。
擴展了一些配置 context 的方法,可是該接口中的方法僅僅在應用啓動或者關閉時調用。
提供了set/get environment的方法;註冊監聽器的方法;固然還有最重要的 refresh 方法。
1/**
2 * Load or refresh the persistent representation of the configuration,
3 * which might an XML file, properties file, or relational database schema.
4 * <p>As this is a startup method, it should destroy already created singletons
5 * if it fails, to avoid dangling resources. In other words, after invocation
6 * of that method, either all or no singletons at all should be instantiated.
7 * @throws BeansException if the bean factory could not be initialized
8 * @throws IllegalStateException if already initialized and multiple refresh
9 * attempts are not supported
10 */
11void refresh() throws BeansException, IllegalStateException;
複製代碼
從註釋中咱們能夠看到該方法的做用:
加載或者刷新持久層的配置資源,好比 xml、property 或者數據庫文件。
由於該方法在應用啓動時調用,因此若是失敗,則要銷燬掉全部已經建立好的單例對象。
換句話說就是:一旦該方法被調用,要麼建立好全部的單例對象,要麼一個單例對象都不會建立。
對於 ConfigurableApplicationContext,該抽象類提供了大部分的模板實現方法。
這裏重點看下 refresh 方法:
1@Override
2public void refresh() throws BeansException, IllegalStateException {
3 synchronized (this.startupShutdownMonitor) {
4 // Prepare this context for refreshing.
5 prepareRefresh();
6
7 // Tell the subclass to refresh the internal bean factory.
8 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
9
10 // Prepare the bean factory for use in this context.
11 prepareBeanFactory(beanFactory);
12
13 try {
14 // Allows post-processing of the bean factory in context subclasses.
15 postProcessBeanFactory(beanFactory);
16
17 // Invoke factory processors registered as beans in the context.
18 invokeBeanFactoryPostProcessors(beanFactory);
19
20 // Register bean processors that intercept bean creation.
21 registerBeanPostProcessors(beanFactory);
22
23 // Initialize message source for this context.
24 initMessageSource();
25
26 // Initialize event multicaster for this context.
27 initApplicationEventMulticaster();
28
29 // Initialize other special beans in specific context subclasses.
30 onRefresh();
31
32 // Check for listener beans and register them.
33 registerListeners();
34
35 // Instantiate all remaining (non-lazy-init) singletons.
36 finishBeanFactoryInitialization(beanFactory);
37
38 // Last step: publish corresponding event.
39 finishRefresh();
40 }
41
42 catch (BeansException ex) {
43 if (logger.isWarnEnabled()) {
44 logger.warn("Exception encountered during context initialization - " +
45 "cancelling refresh attempt: " + ex);
46 }
47
48 // Destroy already created singletons to avoid dangling resources.
49 destroyBeans();
50
51 // Reset 'active' flag.
52 cancelRefresh(ex);
53
54 // Propagate exception to caller.
55 throw ex;
56 }
57
58 finally {
59 // Reset common introspection caches in Spring's core, since we
60 // might not ever need metadata for singleton beans anymore...
61 resetCommonCaches();
62 }
63 }
複製代碼
該方法比較長,可是註釋仍是比較詳細的,咱們能夠逐塊分解的看:
先看第5行(如下提到具體的行數均指的是 refresh 方法中的)中的prepareRefresh:
1protected void prepareRefresh() {
2 // 設置一些容器 active flag 標誌位
3 this.startupDate = System.currentTimeMillis();
4 this.closed.set(false);
5 this.active.set(true);
6
7 // 初始化一些 environment 中的佔位符屬性
8 initPropertySources();
9
10 // 校驗一些標記爲 required 的必要屬性
11 getEnvironment().validateRequiredProperties();
12
13 // 存儲「準備刷新」的一些監聽器.
14 if (this.earlyApplicationListeners == null) {
15 this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
16 }
17 else {
18 // Reset local application listeners to pre-refresh state.
19 this.applicationListeners.clear();
20 this.applicationListeners.addAll(this.earlyApplicationListeners);
21 }
22
23 // 存儲事件
24 this.earlyApplicationEvents = new LinkedHashSet<>();
25}
複製代碼
繼續看第8行的代碼 obtainFreshBeanFactory 發生了什麼:
1protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
2 refreshBeanFactory();
3 return getBeanFactory();
4}
複製代碼
這裏使用了模板方法,refreshBeanFactory 的實現留給子類,官方給出的註釋是:
1/**
2 * 子類必須實現該方法來執行實際的加載工做。
3 */
4protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
複製代碼
getBeanFactory 方法的實現也留給子類,官方的註釋是:
1/**
2 * 子類在這裏必須返回它內部的bean factory.
3 * 這個bean factory 應該實現高效的查詢工做,這樣重複調用時纔不會形成性能損失.
4 * 注意:
5 * 子類在返回 bean factory 以前必須檢查 context 是否屬於 active 狀態;若是處於 close 狀態,則不能獲取該對象。
6 */
7@Override
8public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
複製代碼
第 11 行,prepareBeanFactory 方法:
對於一些 context 的特徵給出了配置,好比加載器、post-processor等。
1protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
2 //設置加載器
3 beanFactory.setBeanClassLoader(getClassLoader());
4 //設置 Spring EL 解析器
5 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
6 //設置用於註冊 PropertyEditor 的註冊機
7 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
8
9 // Configure the bean factory with context callbacks.
10 // 設置一些用於 bean 後期處理的 processor
11 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
12 // 忽略一些依賴接口
13 beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
14 beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
15 beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
16 beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
17 beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
18 beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
19
20 // BeanFactory interface not registered as resolvable type in a plain factory.
21 // MessageSource registered (and found for autowiring) as a bean.
22 // 註冊具備相應自動裝配值得依賴類型
23 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
24 beanFactory.registerResolvableDependency(ResourceLoader.class, this);
25 beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
26 beanFactory.registerResolvableDependency(ApplicationContext.class, this);
27
28 // 註冊該監聽器用於檢測監聽器 bean
29 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
30
31 // Detect a LoadTimeWeaver and prepare for weaving, if found.
32 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
33 beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
34 // Set a temporary ClassLoader for type matching.
35 beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
36 }
37
38 // 註冊默認的 environment beans.
39 if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
40 beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
41 }
42 if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
43 beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
44 }
45 if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
46 beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
47 }
48}
複製代碼
第15行 postProcessBeanFactory 方法:
1protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
2}
複製代碼
也是一個模板方法,官方給出的註釋是:
context 內部的 bean factory 初始化後,在此處進行一些修改。此時全部的bean定義都被加載,可是尚未任何一個bean被實例化。
第 18 行invokeBeanFactoryPostProcessors方法:
1protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
2 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
3
4 // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
5 // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
6 if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
7 beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
8 beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
9 }
10}
複製代碼
此方法的做用在於:實例化全部的bean 以前,實例化並調用一些 context 內部持有的 BeanFactoryPostProcessor。
第21行registerBeanPostProcessors方法:
1protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
2 PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
3}
複製代碼
註冊全部的 bean 後期處理類。
第24行 initMessageSource 方法:
1protected void initMessageSource() {
2 ConfigurableListableBeanFactory beanFactory = getBeanFactory();
3 if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
4 this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
5 // Make MessageSource aware of parent MessageSource.
6 if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
7 HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
8 if (hms.getParentMessageSource() == null) {
9 // Only set parent context as parent MessageSource if no parent MessageSource
10 // registered already.
11 hms.setParentMessageSource(getInternalParentMessageSource());
12 }
13 }
14 if (logger.isTraceEnabled()) {
15 logger.trace("Using MessageSource [" + this.messageSource + "]");
16 }
17 }
18 else {
19 // Use empty MessageSource to be able to accept getMessage calls.
20 DelegatingMessageSource dms = new DelegatingMessageSource();
21 dms.setParentMessageSource(getInternalParentMessageSource());
22 this.messageSource = dms;
23 beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
24 if (logger.isTraceEnabled()) {
25 logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
26 }
27 }
28}
複製代碼
該方法進行了兩方面的處理:
若是此 context中的 beanFactory 有 MessageSource 屬性,則直接獲取其值,並將其父MessageSource 設置到此context 的父context中;
若是此 context 中的 beanFactory 沒有 MessageSource 屬性,則直接使用 parent context中的 MessageSource。
第27行initApplicationEventMulticaster:
1protected void initApplicationEventMulticaster() {
2 ConfigurableListableBeanFactory beanFactory = getBeanFactory();
3 if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
4 this.applicationEventMulticaster =
5 beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
6 //去掉日誌打印
7 else {
8 this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
9 beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
10 //去掉日誌打印
11 }
12 }
13}
複製代碼
此方法初始化 ApplicationEventMulticaster 廣播器。
若是本地 context中有該屬性,則直接獲取值,若是沒有則構造一個默認的SimpleApplicationEventMulticaster。
第30行 onRefresh 方法:
1protected void onRefresh() throws BeansException {
2 // For subclasses: do nothing by default.
3}
複製代碼
又是一個模板方法,留待子類去實現。
主要是增長一些特定context 的 refresh 工做,在一些特殊的 bean 初始化時調用,該調用在任何單例對象實例化以前。
第33行registerListeners,檢出並註冊全部實現了ApplicationListener的監聽器,若是此時有 event,則分發之。
1protected void registerListeners() {
2 // Register statically specified listeners first.
3 for (ApplicationListener<?> listener : getApplicationListeners()) {
4 getApplicationEventMulticaster().addApplicationListener(listener);
5 }
6
7 // Do not initialize FactoryBeans here: We need to leave all regular beans
8 // uninitialized to let post-processors apply to them!
9 String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
10 for (String listenerBeanName : listenerBeanNames) {
11 getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
12 }
13
14 // Publish early application events now that we finally have a multicaster...
15 Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
16 this.earlyApplicationEvents = null;
17 if (earlyEventsToProcess != null) {
18 for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
19 getApplicationEventMulticaster().multicastEvent(earlyEvent);
20 }
21 }
22}
複製代碼
第36行finishBeanFactoryInitialization方法:
完成此 context 中全部 factory bean 的初始化工做,實例化剩下的非惰性加載單例對象。
1protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
2 // Initialize conversion service for this context.
3 if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
4 beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
5 beanFactory.setConversionService(
6 beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
7 }
8
9 // Register a default embedded value resolver if no bean post-processor
10 // (such as a PropertyPlaceholderConfigurer bean) registered any before:
11 // at this point, primarily for resolution in annotation attribute values.
12 if (!beanFactory.hasEmbeddedValueResolver()) {
13 beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
14 }
15
16 // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
17 String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
18 for (String weaverAwareName : weaverAwareNames) {
19 getBean(weaverAwareName);
20 }
21
22 // Stop using the temporary ClassLoader for type matching.
23 beanFactory.setTempClassLoader(null);
24
25 // Allow for caching all bean definition metadata, not expecting further changes.
26 beanFactory.freezeConfiguration();
27
28 // Instantiate all remaining (non-lazy-init) singletons.
29 beanFactory.preInstantiateSingletons();
30}
複製代碼
重點放在下面兩行上:
1// Allow for caching all bean definition metadata, not expecting further changes.
2beanFactory.freezeConfiguration();
3
4// Instantiate all remaining (non-lazy-init) singletons.
5beanFactory.preInstantiateSingletons();
複製代碼
第一步 freeze 全部的 bean定義數據,該定義不能被更改;
第二步 開始真正實例化全部的單例。
第39行finishRefresh方法:
1protected void finishRefresh() {
2 // Clear context-level resource caches (such as ASM metadata from scanning).
3 clearResourceCaches();
4
5 // Initialize lifecycle processor for this context.
6 initLifecycleProcessor();
7
8 // Propagate refresh to lifecycle processor first.
9 getLifecycleProcessor().onRefresh();
10
11 // Publish the final event.
12 publishEvent(new ContextRefreshedEvent(this));
13
14 // Participate in LiveBeansView MBean, if active.
15 LiveBeansView.registerApplicationContext(this);
16}
複製代碼
此時正式宣告完成 context 的refresh 工做,調用 LifecycleProcessor 的 onRefresh 方法,以後發佈 ContextRefreshEvent 事件。
此文對 Spring 中的幾個重要的 context 進行了分析,尤爲是對 AbstractApplicationContext 的主要脈絡進行了梳理。