赞
踩
在 SpringBoot源码解读与原理分析(八)ApplicationContext 中,梳理了是ApplicationContext的几个重要实现类,其中AbstractApplicationContext显得尤为重要:
ApplicationContext的启动,其内部的核心动作的刷新容器,也就是AbstractApplicationContext中的refresh()方法。
AbstractApplicationContext.java public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. // 1.初始化前的预处理 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. // 2.获取BeanFactory,加载所有bean的定义信息(未实例化) ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. // 3.BeanFactory的预处理配置 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. // 4.准备BeanFactory完成后进行的后置处理 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. // 5.执行BeanFactory创建后的后置处理器 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. // 6.注册Bean的后置处理器 registerBeanPostProcessors(beanFactory); // Initialize message source for this context. // 7.初始化MessageSource initMessageSource(); // Initialize event multicaster for this context. // 8.初始化事件广播器 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. // 9.子类的多态onRefresh onRefresh(); // Check for listener beans and register them. // 10.注册监听器 registerListeners(); // 至此,BeanFactory创建完成 // Instantiate all remaining (non-lazy-init) singletons. // 11.初始化所有剩下的单实例 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. // 12.完成容器的创建工作 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... // 13.清理缓存 resetCommonCaches(); } } }
整个refresh方法分为13步,这篇文章只是梳理每一步都做了哪些事情,对于其中的细节设计放到之后的文章再展开。
/** * Prepare this context for refreshing, setting its startup date and * active flag as well as performing any initialization of property sources. */ protected void prepareRefresh() { // Switch to active. // 切换IOC容器启动状态 this.startupDate = System.currentTimeMillis(); this.closed.set(false); this.active.set(true); if (logger.isDebugEnabled()) { if (logger.isTraceEnabled()) { logger.trace("Refreshing " + this); } else { logger.debug("Refreshing " + getDisplayName()); } } // Initialize any placeholder property sources in the context environment. // 在上下文环境中初始化任何占位符属性源 initPropertySources(); // Validate that all properties marked as required are resolvable: // see ConfigurablePropertyResolver#setRequiredProperties // 验证标记为required的所有属性都是可解析的 getEnvironment().validateRequiredProperties(); // Store pre-refresh ApplicationListeners... // 存储预刷新的ApplicationListeners if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); } else { // Reset local application listeners to pre-refresh state. // 将本地应用程序监听器重置为预刷新状态。 this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... // 收集早期ApplicationEvents this.earlyApplicationEvents = new LinkedHashSet<>(); }
这一步骤大多数的动作都是前置性准备,包括切换IOC容器启动状态、初始化属性配置、属性检验、早期事件容器准备等。
AbstractApplicationContext.java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
这一步骤的refreshBeanFactory方法是一个抽象方法,由子类实现。不同的实现行为也不同。
(1)基于注解配置类的落地实现:GenericApplicationContext
GenericApplicationContext.java
@Override
protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
this.beanFactory.setSerializationId(getId());
}
GenericApplicationContext的refreshBeanFactory方法中有一个CSA判断动作,控制着GenericApplicationContext不能反复刷新。
(2)基于XML配置文件的落地实现:AbstractRefreshableApplicationContext
从类名可知,这是可刷新的ApplicationContext。该类的refreshBeanFactory方法会解析XML配置文件,封装BeanDefinition注册到BeanDefinitionRegistry中。
AbstractApplicationContext.java protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // Tell the internal bean factory to use the context's class loader etc. // 注册类加载器、表达式解析器等 beanFactory.setBeanClassLoader(getClassLoader()); beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // Configure the bean factory with context callbacks. // 编程式注册ApplicationContextAwareProcessor beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); // BeanFactory interface not registered as resolvable type in a plain factory. // MessageSource registered (and found for autowiring) as a bean. // 绑定BeanFactory和ApplicationContext的依赖注入映射 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // Register early post-processor for detecting inner beans as ApplicationListeners. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); // Detect a LoadTimeWeaver and prepare for weaving, if found. if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // Set a temporary ClassLoader for type matching. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } // Register default environment beans. // 注册Environment抽象 if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } }
这一步骤的内部处理内容比较多,主要包含三件事情:
AbstractApplicationContext.java
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {}
这一步骤的方法本身是一个模板方法,由子类具体实现。
(1)基于Web环境的实现:GenericWebApplicationContext
GenericWebApplicationContext.java
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
if (this.servletContext != null) {
// 编程式注册ServletContextAwareProcessor
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
}
// 注册新的Bean的作用域
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
// 注册ServletContext
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
}
基于Web环境的实现GenericWebApplicationContext的postProcessBeanFactory方法做了3件事情:
(2)基于嵌入式Web容器的实现:ServletWebServerApplicationContext
ServletWebServerApplicationContext.java
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
registerWebApplicationScopes();
}
这种方式是SpringBoot主要使用的,与基于Web环境的实现GenericWebApplicationContext相比,主要区别有:
PostProcessorRegistrationDelegate.java public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any. // 执行所有的BeanDefinitionRegistryPostProcessor Set<String> processedBeans = new HashSet<>(); if (beanFactory instanceof BeanDefinitionRegistry) { // ... // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. // 执行所有的BeanFactoryPostProcessor List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); List<String> orderedPostProcessorNames = new ArrayList<>(); //... }
这一步骤会回调执行所有的BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor。在 SpringBoot源码解读与原理分析(十二)后置处理器 中详细梳理了这两个后置处理器的作用:
PostProcessorRegistrationDelegate.java
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 初始化所有的BeanPostProcessor
// ...
}
这一步骤会初始化所有的BeanPostProcessor。
在 SpringBoot源码解读与原理分析(十二)后置处理器 中详细梳理了BeanPostProcessor的作用:它可以干预bean对象的实例化、初始化逻辑,postProcessBeforeInitialization在bean对象的初始化逻辑之前执行,postProcessAfterInitialization在初始化逻辑之后执行。另外postProcessAfterInitialization还可以对FactoryBean创建出的真实对象进行后置处理。
当前步骤初始化BeanPostProcessor时,由于容器中还没有初始化任何业务相关的bean对象,所以后续初始化的所有bean对象都会经过BeanPostProcessor的干预。
AbstractApplicationContext.java protected void initMessageSource() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class); // Make MessageSource aware of parent MessageSource. // ... if (logger.isTraceEnabled()) { logger.trace("Using MessageSource [" + this.messageSource + "]"); } } else { // Use empty MessageSource to be able to accept getMessage calls. // 未作配置时使用空的MessageSource DelegatingMessageSource dms = new DelegatingMessageSource(); // ... if (logger.isTraceEnabled()) { logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]"); } } }
这一步骤会初始化默认的国际化组件,但默认的实现类DelegatingMessageSource在不作任何附加配置时不会处理任何国际化的工作,只有手动向IOC容器注册具体的国际化组件,应用上下文才具备国际化的能力。
AbstractApplicationContext.java protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { // 如果手动配置了ApplicationEventMulticaster,则使用配置的 this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isTraceEnabled()) { logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { // 如果没有配置,则使用SimpleApplicationEventMulticaster this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isTraceEnabled()) { logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " + "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]"); } } }
这一步骤会初始化ApplicationEventMulticaster,如果没有手动注册,则使用默认的简单实现SimpleApplicationEventMulticaster。
AbstractApplicationContext.java
protected void onRefresh() throws BeansException {
// For subclasses: do nothing by default.
}
这是一个模板方法,默认没有任何实现。
借助IDEA可以查找到实现了该方法的类:
ReactiveWebServerApplicationContext中的扩展用于初始化基于Reactive环境的Web容器,ServletWebServerApplicationContext中的扩展用于初始化基于Servlet环境的Web容器。
AbstractApplicationContext.java protected void registerListeners() { // Register statically specified listeners first. // 注册静态指定的监听器 for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let post-processors apply to them! // 只绑定baenName而不直接取出监听器的原因:不让所有常规bean对象初始化 // 后置处理器才能有机会干预 String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } // Publish early application events now that we finally have a multicaster... Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (!CollectionUtils.isEmpty(earlyEventsToProcess)) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }
这一步骤讲BeanDefinitionRegistry中注册的所有监听器(ApplicationListener)的beanName取出,绑定到事件广播器(ApplicationEventMulticaster)中。只绑定beanName而不直接取出监听器的原因是,考虑到ApplicationListener作为IOC容器中的Bean,应该和其他常规Bean放在一起统一创建和初始化,以让后置处理器有机会干预它们。
AbstractApplicationContext.java protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // Initialize conversion service for this context. // 初始化用于类型转换的解析器 if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // Register a default embedded value resolver if no BeanFactoryPostProcessor // (such as a PropertySourcesPlaceholderConfigurer bean) registered any before: // at this point, primarily for resolution in annotation attribute values. // 初始化用于表达式解析的解析器 if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. // 初始化所有非延迟加载的单实例bean对象 String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // Stop using the temporary ClassLoader for type matching. beanFactory.setTempClassLoader(null); // Allow for caching all bean definition metadata, not expecting further changes. beanFactory.freezeConfiguration(); // Instantiate all remaining (non-lazy-init) singletons. beanFactory.preInstantiateSingletons(); }
这一步骤主要完成2件事情,并且该步骤执行完毕后,BeanFactory的初始化工作结束:
这一步骤执行了一些比较零散的动作,详见注释。
AbstractApplicationContext.java protected void finishRefresh() { // Clear context-level resource caches (such as ASM metadata from scanning). // 清理上下文级别的资源缓存(例如扫描中的ASM元数据) clearResourceCaches(); // Initialize lifecycle processor for this context. // 初始化生命周期处理器 initLifecycleProcessor(); // Propagate refresh to lifecycle processor first. // 传播生命周期处理器,回调所有Lifecycle类型Bean的start方法 getLifecycleProcessor().onRefresh(); // Publish the final event. // 广播ContextRefreshedEvent事件 publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. // 激活状态下,参与LiveBeansView MBean LiveBeansView.registerApplicationContext(this); }
AbstractApplicationContext.java
protected void resetCommonCaches() {
ReflectionUtils.clearCache();
AnnotationUtils.clearCache();
ResolvableType.clearCache();
CachedIntrospectionResults.clearClassLoader(getClassLoader());
}
这一步骤清除一些无用的缓存,包括ReflectionUtils、AnnotationUtils、ResolvableType、CachedIntrospectionResults中的缓存。
总结:
纵观整个refresh方法,每个动作的职责都很清晰。在整个过程中,有对BeanFactory的处理,有对ApplicationContext的处理,有准备BeanPostProcessor的处理,有准备ApplicationListener的逻辑,最后初始化一些非延迟加载的单实例bean对象。refresh方法执行完毕后,也就宣告对ApplicationContext初始化完成。
第3章到此就梳理完毕了,本章的主题是SpringBoot的IOC容器。回顾一下本章的梳理的内容:
(七)BeanFactory
(八)ApplicationContext
(九)SpringBoot对IOC容器的拓展
(十)Environment
(十一)BeanDefinition
(十二)后置处理器
(十三)IOC容器的启动流程
更多内容请查阅分类专栏:SpringBoot源码解读与原理分析
第4章主要梳理SpringBoot的核心引导:SpringApplication。主要内容包括:
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。