Spring 中的 context
BeanFactory
首先看下,官方在代码中给出的注释:
The root interface for accessing a Spring bean container.This is the basic client view of a bean container。
是接触所有Spring bean容器的根接口,这个接口被持有大量bean定义的对象实现。
从其接口中定义的方法即可看出,其为bean容器的真正含义。
ListableBeanFactory 继承了 BeanFactory,为其提供了枚举所有 beans 的方法:
ApplicationContext
而 ApplicationContext 类通过对该接口的扩展,提供了为application提供配置的扩展接口。
根据官方给出的注释,其总共功能有以下几点:
- 对应用的 component 的工厂方法;
- 一种通用的加载资源文件的方式;
- 对注册的监听器发布事件的能力;
- 解析message,支持国家化的能力。
这些能力主要通过继承各种接口获得,其自身接口主要扩展的重要方法主要有一个:
1@Nullable 2ApplicationContext getParent(); 复制代码
在 SpringBoot 中,context 有其继承体系:每个不同的 servlet 都有自己独立的 context,而整个 application 有一个根 context,这个 context 是所有 servlet 所共享的。
所以此处提供了获得父 context 的能力。
ConfigurableApplicationContext
全部或者绝大多数 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 *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 或者数据库文件。
因为该方法在应用启动时调用,所以如果失败,则要销毁掉所有已经创建好的单例对象。
换句话说就是:一旦该方法被调用,要么创建好所有的单例对象,要么一个单例对象都不会创建。
AbstractApplicationContext
对于 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 SetearlyEventsToProcess = 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 的主要脉络进行了梳理。