ApplicationContext和BeanFactory都是用于加载bean的,但是相比之下,ApplicationContext提供了更多的扩展功能,ApplicationContext包含BeanFactory的所有功能,通常建议比BeanFactory优先,除非在一些限制的场合,比如字节长度对内存有很大的影响时。
我们以ClassPathXmlApplicationContext作为切入点,对整体功能进行分析:
/**
* 从类路径中加载XML应用程序上下文,配置文件路径来自类路径,
* 直接将类路径资源名称作为路径参数,包括包路径(例如:"mypackage/myresource.txt")。
* 适用于测试框架以及嵌入在jar文件中的应用程序上下文。
*
* <p>配置位置的默认位置可以被重写 via {@link #getConfigLocations},
* 配置位置可以表示文件路径(如"/myfiles/context.xml")或者通配符模式(如"/myfiles/*-context.xml")(有关模式的详细信息,请参阅
* {@link org.springframework.util.AntPathMatcher} javadoc)。
*
* <p>注意:如果存在多个配置位置,那么后面的bean定义将覆盖前面加载的文件中的bean定义。
* 可以利用这一点通过额外的XML文件有意图覆盖某些bean定义。
*
* <p><b>这是一个简单的单例应用程序上下文便利类。
* 考虑与 {@link GenericApplicationContext} 类一起使用,结合
* {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader} 来实现更灵活的上下文设置。</b>
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see #getResource
* @see #getResourceByPath
* @see GenericApplicationContext
*/
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
@Nullable
private Resource[] configResources;
/**
* 创建一个新的 ClassPathXmlApplicationContext 来进行bean-style配置。
* @see #setConfigLocation
* @see #setConfigLocations
* @see #afterPropertiesSet()
*/
public ClassPathXmlApplicationContext() {
}
/**
* 创建一个新的 ClassPathXmlApplicationContext,使用给定的父上下文,并进行bean-style配置。
* @param parent 父上下文
* @see #setConfigLocation
* @see #setConfigLocations
* @see #afterPropertiesSet()
*/
public ClassPathXmlApplicationContext(ApplicationContext parent) {
super(parent);
}
/**
* 创建一个新的 ClassPathXmlApplicationContext,加载给定的XML文件,并自动刷新上下文。
* @param configLocation 资源位置
* @throws BeansException 如果上下文创建失败
*/
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
/**
* 创建一个新的 ClassPathXmlApplicationContext,加载给定的XML文件集,并自动刷新上下文。
* @param configLocations 资源位置数组
* @throws BeansException 如果上下文创建失败
*/
public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
this(configLocations, true, null);
}
/**
* 创建一个新的 ClassPathXmlApplicationContext,带有给定的父上下文,加载给定的XML文件集,并自动刷新上下文。
* @param configLocations 资源位置数组
* @param parent 父上下文
* @throws BeansException 如果上下文创建失败
*/
public ClassPathXmlApplicationContext(String[] configLocations, @Nullable ApplicationContext parent)
throws BeansException {
this(configLocations, true, parent);
}
/**
* 创建一个新的 ClassPathXmlApplicationContext,加载给定的XML文件集。
* @param configLocations 资源位置数组
* @param refresh 是否自动刷新上下文,
* 加载所有bean定义并创建所有单例。
* 在进一步配置上下文后,可以选择手动刷新该上下文。
* @throws BeansException 如果上下文创建失败
* @see #refresh()
*/
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
this(configLocations, refresh, null);
}
/**
* 创建一个新的 ClassPathXmlApplicationContext,带有给定的父上下文,加载给定的XML文件集。
* @param configLocations 资源位置数组
* @param refresh 是否自动刷新上下文,
* 加载所有bean定义并创建所有单例。
* 在进一步配置上下文后,可以选择手动刷新该上下文。
* @param parent 父上下文
* @throws BeansException 如果上下文创建失败
* @see #refresh()
*/
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
/**
* 创建一个新的 ClassPathXmlApplicationContext,加载给定的XML文件,并自动刷新上下文。
* <p>这是一个方便的方法,用于加载类路径资源并与给定的 Class 相关联。为了实现完全的灵活性,
* 考虑使用 GenericApplicationContext 和 XmlBeanDefinitionReader,
* 并传递一个 ClassPathResource 作为参数。
* @param path 类路径中的相对(或绝对)路径
* @param clazz 资源要加载的类(给定路径的基础)
* @throws BeansException 如果上下文创建失败
* @see org.springframework.core.io.ClassPathResource#ClassPathResource(String, Class)
* @see org.springframework.context.support.GenericApplicationContext
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
*/
public ClassPathXmlApplicationContext(String path, Class<?> clazz) throws BeansException {
this(new String[] {path}, clazz);
}
/**
* 创建一个新的 ClassPathXmlApplicationContext,加载给定的XML文件集,并自动刷新上下文。
* @param paths 类路径中的相对(或绝对)路径数组
* @param clazz 资源要加载的类(给定路径的基础)
* @throws BeansException 如果上下文创建失败
* @see org.springframework.core.io.ClassPathResource#ClassPathResource(String, Class)
* @see org.springframework.context.support.GenericApplicationContext
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
*/
public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz) throws BeansException {
this(paths, clazz, null);
}
/**
* 创建一个新的 ClassPathXmlApplicationContext,带有给定的父上下文,加载给定的XML文件集,并自动刷新上下文。
* @param paths 类路径中的相对(或绝对)路径数组
* @param clazz 资源要加载的类(给定路径的基础)
* @param parent 父上下文
* @throws BeansException 如果上下文创建失败
* @see org.springframework.core.io.ClassPathResource#ClassPathResource(String, Class)
* @see org.springframework.context.support.GenericApplicationContext
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
*/
public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
Assert.notNull(paths, "Path array must not be null");
Assert.notNull(clazz, "Class argument must not be null");
this.configResources = new Resource[paths.length];
for (int i = 0; i < paths.length; i++) {
this.configResources[i] = new ClassPathResource(paths[i], clazz);
}
refresh();
}
@Override
@Nullable
protected Resource[] getConfigResources() {
return this.configResources;
}
}
设置了路径是必不可少的步骤,ClassPathXmlApplicationContext中可以将配置文件路径以数组的方式传入,可以对数组进行解析并加载。而对于解析及功能功能实现都是在refresh()中实现的。refresh()函数的源码如下:
/**
* 刷新当前上下文,重新创建内部bean工厂并执行上下文的销毁和创建过程。
*
* @throws BeansException 当无法刷新上下文时抛出
* @throws IllegalStateException 当上下文状态不允许刷新时抛出
*/
@Override
public void refresh() throws BeansException, IllegalStateException {
this.startupShutdownLock.lock();
try {
this.startupShutdownThread = Thread.currentThread();
// 记录开始刷新的启动步骤
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 准备刷新当前上下文
prepareRefresh();
// 告知子类刷新内部bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备bean工厂以在当前上下文中使用
prepareBeanFactory(beanFactory);
try {
// 允许在上下文中注册后的bean工厂进行后处理
postProcessBeanFactory(beanFactory);
// 启动步骤记录bean创建后的处理步骤
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// 调用作为上下文中的bean注册的工厂后处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 注册创建bean之前的处理器
registerBeanPostProcessors(beanFactory);
// 结束bean处理步骤
beanPostProcess.end();
// 初始化消息源
initMessageSource();
// 初始化事件多播器
initApplicationEventMulticaster();
// 在特定的上下文子类中初始化其他特殊bean
onRefresh();
// 检查监听器bean并进行注册
registerListeners();
// 完成bean工厂的初始化
finishBeanFactoryInitialization(beanFactory);
// 最后一步:发布相应的事件
finishRefresh();
} catch (RuntimeException | Error ex) {
if (logger.isWarnEnabled()) {
logger.warn("初始化上下文期间遇到异常 - 取消刷新尝试:" + ex);
}
// 销毁已经创建的bean以避免挂起资源
destroyBeans();
// 重置'active'标志
cancelRefresh(ex);
// 将异常传递给调用者
throw ex;
} finally {
// 结束刷新的启动步骤
contextRefresh.end();
}
} finally {
// 重置启动/关闭线程和锁
this.startupShutdownThread = null;
this.startupShutdownLock.unlock();
}
}
下面概括一下ClassPathXmlApplicationContext初始化的步骤,并从中解释一下它为我们提供的功能。
- 初始化前的准备工作,例如对系统属性或者环境变量进行准备及验证。
- 初始化BeanFactory,并进行XML文件读取。之前有提到ClassPathXmlApplicationContext包含着BeanFactory所提供的一切特征,那么在这一步骤中将会复用BeanFactory中配置文件读取解析及其他功能,这一步之后,ClassPathXmlApplicationContext实际上就已经包含了BeanFactory所提供的功能,也就是可以进行bean的提取操作了。
- 对BeanFactory进行各种功能填充,@Qualifier与@Autowired这两个注解正是在这一步骤中增加的支持。
- 子类覆盖方法做额外的处理。
- 激活各种BeanFactory处理器。
- 注册拦截bean创建的bean处理器,这里只是注册,真正的调用是在getBean时候
- 为上下文初始化Message源,即对不同语言的消息体进行国际化处理。
- 初始化应用消息广播器,并放入applicationEventMulticaster的bean中。
- 留给子类来初始化其他的bean。
- 在所有注册的bean中查找listener bean,注册到消息广播器中。
- 初始化剩下的单实例(非惰性的)。
- 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发送ContextRefreshEvent通知其他对象。
环境准备
prepareRefresh函数主要是做些准备工作,例如对系统属性及环境变量的初始化及验证。
/**
* 为上下文准备刷新操作,设置其启动时间、活动标志以及进行任何属性源的初始化。
*/
protected void prepareRefresh() {
// 切换为活动状态。
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("正在刷新 " + this);
}
else {
logger.debug("正在刷新 " + getDisplayName());
}
}
// 在上下文环境中初始化任何占位符属性源。
initPropertySources();
// 验证所有标记为必需的属性是否可解析:见ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// 存储刷新前的ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// 重置本地ApplicationListeners到刷新前状态。
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// 支持早期ApplicationEvents的收集,
// 在多播器可用时发布...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
这个函数用于准备刷新上下文,包括设置活动标志,初始化属性源,验证必需的属性是否可解析,存储刷新前的ApplicationListeners,以及收集早期的ApplicationEvents。
加载BeanFactory
ApplicationContext是对BeanFactory的功能上的扩展,不但包含了BeanFactory的全部功能更在其基础上添加了大量的扩展应用,那么obtainFreshBeanFactory方法正是实现BeanFactory的地方,也就是经过这个函数后ApplicationContext就已经拥有了BeanFactory的全部功能。
/**
* 获取刷新后的bean工厂。
* @return 返回BeanFactory实例
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 初始化BeanFactory,并进行XML文件读取,并将得到的BeanFactory记录到当前实体的属性中
refreshBeanFactory();
// 返回当前实体的BeanFactory属性
return getBeanFactory();
}
上述方法将核心实现委托给了refreshBeanFactory,源码如下:
/**
* 该实现会实际刷新该上下文的底层bean工厂,在上下文生命周期的下个阶段初始化一个新的bean工厂。
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建DefaultListableBeanFactory实例
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 为了序列化指定id,如果需要的话,让这个beanFactory从id反序列化到BeanFactory对象
beanFactory.setSerializationId(getId());
// 定制beanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象
// 以及循环依赖
customizeBeanFactory(beanFactory);
// 初始化DocumentReader,并进行XML文件的读取和解析
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("解析bean定义源时发生I/O错误:" + getDisplayName(), ex);
}
}
这个函数是一个重写的方法,用于刷新上下文的内部bean工厂。如果已经有现有的bean工厂,该函数会关闭之前的bean工厂并初始化一个新的bean工厂。首先检查是否有现有的bean工厂,如果有则销毁所有bean并关闭bean工厂。然后创建一个新的DefaultListableBeanFactory对象,并设置序列号。然后自定义bean工厂并加载bean定义。最后将bean工厂赋值给类成员变量。如果发生I/O错误则抛出ApplicationContextException异常。
定制BeanFactory
这里已经开始了对BeanFactory的扩展,在基本容器的基础上,增加了是否允许覆盖是否允许扩展的设置。源码如下:
/**
* 自定义此上下文使用的内部bean工厂。
* 在每次调用{@link #refresh()}时都会调用此方法。
* <p>默认实现应用此上下文的
* {@linkplain #setAllowBeanDefinitionOverriding "allowBeanDefinitionOverriding"}
* 和
* {@linkplain #setAllowCircularReferences "allowCircularReferences"}
* 设置,如果已经指定。可以在子类中重写以自定义
* {@link DefaultListableBeanFactory}的任何设置。
* @param beanFactory 对于此上下文的新创建的bean工厂
* @see DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
* @see DefaultListableBeanFactory#setAllowCircularReferences
* @see DefaultListableBeanFactory#setAllowRawInjectionDespiteWrapping
* @see DefaultListableBeanFactory#setAllowEagerClassLoading
*/
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
加载BeanDefinition
在第一步中提到了将ClassPathXmlApplicationContext与XmlBeanFactory创建的对比,在实现配置文件的加载功能中除了我们在第一步中已经初始化的DefaultListableBeanFactory外,还需要XmlBeanDefinitionReader来读取XML,那么在这个步骤中首先要做的就是初始化XmlBeanDefinitionReader。
/**
* 通过 XmlBeanDefinitionReader 加载 bean 定义。
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
* @see #initBeanDefinitionReader
* @see #loadBeanDefinitions
*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 创建给定 BeanFactory 的 XmlBeanDefinitionReader。
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 使用该上下文的资源加载环境配置 bean 定义读取器。
beanDefinitionReader.setEnvironment(getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 允许子类提供自定义的读取器初始化,然后实际加载 bean 定义。
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
在初始化了DefaultListableBeanFactory和XmlBeanDefinitionReader后就可以进行配置文件的读取了。
/**
* 使用给定的XmlBeanDefinitionReader加载bean定义。
* <p>bean工厂的生命周期由{@link #refreshBeanFactory}方法处理,
* 因此此方法仅应用于加载和/或注册bean定义。
* @param reader 要使用的XmlBeanDefinitionReader
* @throws BeansException 在bean注册错误时抛出
* @throws IOException 如果找不到所需的XML文档
* @see #refreshBeanFactory
* @see #getConfigLocations
* @see #getResources
* @see #getResourcePatternResolver
*/
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
这个函数用于使用给定的XmlBeanDefinitionReader加载bean定义。bean工厂的生命周期由另一个方法处理,因此此方法仅负责加载和/或注册bean定义。它首先获取配置资源,然后使用XmlBeanDefinitionReader加载bean定义。然后获取配置位置,再使用XmlBeanDefinitionReader加载bean定义。
功能扩展
进入函数prepareBeanFactory前,Spring已经完成了对配置的解析,而ApplicationContext在功能上的扩展也由此展开。源码如下:
/**
* 配置工厂的标准上下文特性,如上下文的类加载器和后处理器。
* @param beanFactory 要配置的 BeanFactory
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置beanFactory的ClassLoader为当前context的ClassLoader
beanFactory.setBeanClassLoader(getClassLoader());
// 设置beanFactory的表达式语言处理器,Spring3增加了对表达式语言的支持
// 默认可以使用#{bean.xxx}的形式来调用相关属性值。
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 为beanFactory增加了一个默认的PropertyEditor,这个主要是对bean的属性等设置管理的一个工具
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 使用上下文回调配置 bean 工厂
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.ignoreDependencyInterface(ApplicationStartupAware.class);
// 设置了几个自动装配的特殊规则
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 早期检测内部的 inner bean 并将其识别为 ApplicationListeners
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 如果发现 LoadTimeWeaver,则检测并准备进行编织
if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// 设置临时的类加载器用于类型匹配
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 注册默认环境 bean
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());
}
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
}
}
增加SpELl语言的支持
通过代码beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()))注册解析器,就可以对SpEL进行解析了,那么在注册解析器后Spring又是在什么时候调用这个解析器进行解析呢?Spring在bean进行初始化的时候会有属性填充的一步,而在这一步中,Spring会调用AbstractAutowireCapableBeanFactory类的applyPropertyValues函数来完成功能。就在这个函数中,会通过构造BeanDefinitionValueResolver类型实例valueResolver来进行属性值的解析。同时,也是在这一步骤中一般通过AbstractBeanFactory中的evaluateBeanDefinitionString方法来完成SpEL的解析。源码如下:
/**
* 对给定的字符串进行评估,将其作为包含在bean定义中的字符串进行处理,可能将其解析为表达式。
* @param value 需要检查的值
* @param beanDefinition 包含有该值的bean定义
* @return 解析后的值
* @see #setBeanExpressionResolver
*/
@Nullable
protected Object evaluateBeanDefinitionString(@Nullable String value, @Nullable BeanDefinition beanDefinition) {
if (this.beanExpressionResolver == null) {
return value;
}
Scope scope = null;
if (beanDefinition != null) {
String scopeName = beanDefinition.getScope();
if (scopeName != null) {
scope = getRegisteredScope(scopeName);
}
}
return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
}
这个函数用于评估一个字符串,可能将其解析为一个表达式。如果bean定义中存在bean表达式解析器,则使用表达式解析器来解析字符串。如果给定bean定义存在作用域,则将其传递给表达式解析器进行评估,否则返回原始字符串。执行表达式的代码逻辑主要是在org.springframework.context.expression.StandardBeanExpressionResolver类的evaluate函数中执行的,源码如下:
/**
* 重写父类方法,用于评估表达式并返回结果。
*
* @param value 表达式字符串
* @param beanExpressionContext 表达式上下文
* @return 评估结果
* @throws BeansException 如果表达式解析失败
*/
@Override
@Nullable
public Object evaluate(@Nullable String value, BeanExpressionContext beanExpressionContext) throws BeansException {
if (!StringUtils.hasLength(value)) {
return value;
}
try {
Expression expr = this.expressionCache.get(value);
if (expr == null) {
expr = this.expressionParser.parseExpression(value, this.beanExpressionParserContext);
this.expressionCache.put(value, expr);
}
StandardEvaluationContext sec = this.evaluationCache.get(beanExpressionContext);
if (sec == null) {
sec = new StandardEvaluationContext(beanExpressionContext);
// 添加属性访问器,用于访问额外的属性
sec.addPropertyAccessor(new BeanExpressionContextAccessor());
sec.addPropertyAccessor(new BeanFactoryAccessor());
sec.addPropertyAccessor(new MapAccessor());
sec.addPropertyAccessor(new EnvironmentAccessor());
// 设置 Bean 解析器
sec.setBeanResolver(new BeanFactoryResolver(beanExpressionContext.getBeanFactory()));
// 设置类型定位器
sec.setTypeLocator(new StandardTypeLocator(beanExpressionContext.getBeanFactory().getBeanClassLoader()));
// 设置类型转换器
sec.setTypeConverter(new StandardTypeConverter(() -> {
ConversionService cs = beanExpressionContext.getBeanFactory().getConversionService();
return (cs != null ? cs : DefaultConversionService.getSharedInstance());
}));
customizeEvaluationContext(sec);
this.evaluationCache.put(beanExpressionContext, sec);
}
return expr.getValue(sec);
}
catch (Throwable ex) {
throw new BeanExpressionException("表达式解析失败", ex);
}
}
这个函数是一个evaluate方法,用于计算并返回给定表达式的结果。它接受一个字符串值和一个BeanExpressionContext对象作为参数。如果字符串值为空,它将返回空值。否则,它会尝试从缓存中获取表达式,如果缓存中没有,则解析表达式并将其添加到缓存中。然后,它从缓存中获取StandardEvaluationContext对象,如果缓存中没有,则创建一个新的,并添加一些属性访问器和一个BeanFactoryResolver来设置Bean工厂。接下来,它使用StandardTypeLocator和StandardTypeConverter设置EvaluationContext,并调用自定义方法对EvaluationContext进行进一步配置。最后,它计算并返回表达式的结果。如果在解析或计算过程中发生异常,它将抛出一个BeanExpressionException异常。
增加属性注册编辑器
XML配置文件字段的类型是字符串的,而对象字段的类型可能是其他类型的,如果直接转换会出现错误。例如日期类型、Spring针对此问题提供了两种解决方法。
使用自定义属性编辑器
使用自定义属性编辑器,通过继承PropertyEditorSupport,重写setAsText方法,具体步骤如下。
编写自定义的属性编辑器
public class LocalDateEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.hasText(text)) {
setValue(DateUtils.parseLocalDate(text.trim()));
}
else {
setValue(null);
}
}
@Override
public String getAsText() {
LocalDate value = (LocalDate) getValue();
return DateUtils.format(value);
}
}
将自定义属性编辑器注册到Spring中
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.time.LocalDate value="org.springframework.beans.propertyeditors.LocalDateEditor"/>
</map>
</property>
</bean>
注册Spring自带的属性编辑器
定义属性编辑器
public class DatePropertyEditorRegistrar implements PropertyEditorRegistrar {
@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(Date.class, new CustomDateEditor(
new SimpleDateFormat("yyyy-MM-dd"), true));
registry.registerCustomEditor(LocalDate.class, new LocalDateEditor());
registry.registerCustomEditor(LocalDateTime.class, new LocalDateTimeEditor());
}
}
注册到Spring中
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="propertyEditorRegistrars">
<list>
<bean class="org.springframework.beans.support.DatePropertyEditorRegistrar"/>
</list>
</property>
</bean>
添加ApplicationContextAwareProcessor处理器
对于beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this))其实主要目的就是注册个BeanPostProcessor,而真正的逻辑还是在ApplicationContextAwareProcessor中。ApplicationContextAwareProcessor实现了BeanPostProcessor接口,在bean实例化的时候,也就是Spring激活bean的init-method的前后会调用BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法。我们重点看一下ApplicationContextAwareProcessor类的源码
/**
* {@link BeanPostProcessor} 的实现类,为实现了 {@code EnvironmentAware}、
* {@code EmbeddedValueResolverAware}、
* {@code ResourceLoaderAware}、
* {@code ApplicationEventPublisherAware}、
* {@code MessageSourceAware} 和/或 {@code ApplicationContextAware} 接口的 {@code ApplicationContext}
* 提供 {@code EnvironmentAware}、
* {@code EmbeddedValueResolverAware}、
* {@code ResourceLoaderAware}、
* {@code ApplicationEventPublisherAware}、
* {@code MessageSourceAware} 和/或 {@code ApplicationContextAware} 接口。
*
* <p>实现的接口按照上面提到的顺序进行满足。
*
* <p>ApplicationContext 会自动将其与此处的 bean 工厂进行注册。应用程序无需直接使用。
*
* @author Juergen Hoeller
* @author Costin Leau
* @author Chris Beams
* @author Sam Brannen
* @since 10.10.2003
* @see org.springframework.context.EnvironmentAware
* @see org.springframework.context.EmbeddedValueResolverAware
* @see org.springframework.context.ResourceLoaderAware
* @see org.springframework.context.ApplicationEventPublisherAware
* @see org.springframework.context.MessageSourceAware
* @see org.springframework.context.ApplicationContextAware
* @see org.springframework.context.support.AbstractApplicationContext#refresh()
*/
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
/**
* 创建一个用于给定上下文的 ApplicationContextAwareProcessor。
*/
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
}
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
bean instanceof ApplicationStartupAware)) {
return bean;
}
invokeAwareInterfaces(bean);
return bean;
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware environmentAware) {
environmentAware.setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware embeddedValueResolverAware) {
embeddedValueResolverAware.setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware resourceLoaderAware) {
resourceLoaderAware.setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware applicationEventPublisherAware) {
applicationEventPublisherAware.setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware messageSourceAware) {
messageSourceAware.setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationStartupAware applicationStartupAware) {
applicationStartupAware.setApplicationStartup(this.applicationContext.getApplicationStartup());
}
if (bean instanceof ApplicationContextAware applicationContextAware) {
applicationContextAware.setApplicationContext(this.applicationContext);
}
}
}
}
设置忽略依赖
当Spring将ApplicationContextAwareProcessor注册后,那么在invokeAwareInterfaces方法中间接调用的Aware类已经不是普通的bean了,如ResourceLoaderAware、ApplicationEventPublisherAware等,那么当然需要在Spring做bean的依赖注入的时候忽略它们。而ignoreDependencyInterface的作用正是如此。
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.ignoreDependencyInterface(ApplicationStartupAware.class);
注册依赖
Spring中有了忽略依赖的功能,当然也必不可少地会有注册依赖的功能。
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
BeanFactory的后处理
BeanFactory作为Spring中容器功能的基础,用于存放所有已经加载的bean,为了保证程序上的扩展性,Spring针对BeanFactory做了大量的扩展。
激活注册的BeanFactoryPostProcessor
BeanFactoryPostProcessor接口跟BeanPostProcessor类似,可以对bean的定义(配置元数据)进行处理。
/**
* 实例化和调用所有已注册的 BeanFactoryPostProcessor 接口的实例,
* 如果有显式顺序要求,则尊重顺序。
* <p>在单例实例化之前必须调用。
*/
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// 检测 LoadTimeWeaver 并进行编织的准备工作,如果在该方法调用期间发现(例如通过 ConfigurationClassPostProcessor 的 @Bean 方法注册)
// (前提是不在原生图像中)
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null &&
beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
该函数用于调用已注册的BeanFactoryPostProcessor bean,以在创建单例bean之前对其进行配置。它首先调用PostProcessorRegistrationDelegate类的方法invokeBeanFactoryPostProcessors来执行beanFactoryPostProcessors的初始化。然后,它检测是否存在LoadTimeWeaver并准备进行接丝处理。如果beanFactory中没有NativeImage并且没有临时类加载器,并且存在LOAD_TIME_WEAVER_BEAN_NAME bean,则会添加LoadTimeWeaverAwareProcessor bean后处理器并设置临时类加载器为ContextTypeMatchClassLoader。invokeBeanFactoryPostProcessors的源码如下:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 提前警告:尽管方法体可能看起来可以被重构来避免使用多个循环和多个列表,
// 但是使用多个列表和多个处理器名称的遍历是为了确保满足PriorityOrdered
// 和Ordered处理器的合同。我们必须确保不会在处理程序实例化(通过getBean()
// 调用)或注册ApplicationContext中导致处理程序在错误的顺序出现。
// 在提交 pull request(PR)之前,请先查看所有已关闭的涉及
// PostProcessorRegistrationDelegate的问题以确保您的提议不会导致破坏性变更:
// 首先,invoke BeanDefinitionRegistryPostProcessors,如果有的话。
Set<String> processedBeans = new HashSet<>();
// 对BeanDefinitionRegistry类型的处理
if (beanFactory instanceof BeanDefinitionRegistry registry) {
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 硬编码注册的后处理器
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor registryProcessor) {
// 对于BeanDefinitionRegistryPostProcessor类型,在BeanFactoryPostProcessor
// 基础上还有自己定义的方法需要先调用
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
// 记录常规的BeanFactoryPostProcessor
regularPostProcessors.add(postProcessor);
}
}
// 不要在这里初始化FactoryBeans:我们需要让bean工厂post-processors应用到它们!
// 分离BeanDefinitionRegistryPostProcessors中实现PriorityOrdered,Ordered和其余部分的处理器。
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 首先,调用实现PriorityOrdered的BeanDefinitionRegistryPostProcessors。
String[] postProcessorNames = beanFactory.getBeanNamesForType(
BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(
ppName, BeanDefinitionRegistryPostProcessor.class));
registryProcessors.add(currentRegistryProcessors);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 激活postProcessBeanFactory方法,之前激活的是postProcessBeanDefinitionRegistry
// 硬编码设置的BeanDefinitionRegistryPostProcessor,优先处理实现PriorityOrdered的处理器
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors
, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
// 接下来,调用实现Ordered的BeanDefinitionRegistryPostProcessors。
postProcessorNames = beanFactory.getBeanNamesForType(
BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
registryProcessors.add(currentRegistryProcessors);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 配置的BeanDefinitionRegistryPostProcessors,然后处理实现Ordered的处理器
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
// 最后调用没有实现PriorityOrdered或Ordered的接口的其他BeanDefinitionRegistryPostProcessor处理器。
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
registryProcessors.add(currentRegistryProcessors);
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 常规的BeanDefinitionRegistryPostProcessors,没有实现PriorityOrdered或Ordered的接口的其他处理器。
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
// 现在,调用之前处理的所有处理器的postProcessBeanFactory回调。
// registryProcessors是BeanDefinitionRegistryPostProcessor类型的
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// regularPostProcessors不是BeanDefinitionRegistryPostProcessor类型的,
// 是BeanFactoryPostProcessor类型的
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// 导入工厂处理器,这些处理器是与上下文实例一起注册的。
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 不要在这里初始化FactoryBeans:我们需要让bean工厂post-processors应用到它们!
// 分离BeanFactoryPostProcessor,实现PriorityOrdered,Ordered和其他处理器。
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// 跳过 - 已经在上面的第一阶段处理
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 实现PriorityOrdered接口的BeanFactoryPostProcessor处理器
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
// 实现Ordered接口的BeanFactoryPostProcessor处理器
orderedPostProcessorNames.add(ppName);
}
else {
// 没有实现Ordered接口的BeanFactoryPostProcessor处理器
nonOrderedPostProcessorNames.add(ppName);
}
}
// 首先,调用实现PriorityOrdered的BeanFactoryPostProcessors。
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 接下来,调用实现Ordered的BeanFactoryPostProcessors。
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 最后,调用所有其他BeanFactoryPostProcessors。
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// 清除合并的bean定义的缓存元数据,因为post-processors可能已经修改了原始元数据...
beanFactory.clearMetadataCache();
}
从上面的方法中我们看到,对于BeanFactoryPostProcessor的处理主要分两种情况,一个是对于BeanDefinitionRegistry类的特殊处理,另一种是对普通的BeanFactoryPostProcessor进行处理。而对于每种情况都需要考虑硬编码注入注册的后处理器以及通过配置注入的后处理器。对于BeanDefinitionRegistry类型的处理类的处理主要包括以下内容。
1、对于硬编码注册的后处理器的处理,主要是通过AbstractApplicationContext中的添加处理器方法addBeanFactoryPostProcessor进行添加的,源码如下:
@Override
public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
this.beanFactoryPostProcessors.add(postProcessor);
}
添加后的后处理器会存放到beanFactoryPostProcessors中,而在处理BeanFactoryPostProcessor的时候会首先检测beanFactoryPostProcessors是否有数据。当然,BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,不但实现了BeanFactoryPostProcessor的方法,还有自定义的方法,也需要在这里进行调用。所以这需要从beanFactoryPostProcessors中挑出BeanDefinitionRegistryPostProcessor的后处理器,并调用postProcessBeanDefinitionRegistry方法进行注册。
2、记录后处理器主要使用了3个List完成。
- registryProcessors:记录通过硬编码方式注册的BeanDefinitionRegistryPostProcessor类型的处理器。
- regularPostProcessors:记录通过硬编码方式注册的BeanFactoryPostProcessor类型的处理器。
3、对以上所记录的List中的处理器统一调用BeanFactoryPostProcessor的postProcessBeanFactory方法。
PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法中处理registryProcessors和regularPostProcessors源码如下:
// 现在,调用之前处理的所有处理器的postProcessBeanFactory回调。
// registryProcessors是BeanDefinitionRegistryPostProcessor类型的
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// regularPostProcessors不是BeanDefinitionRegistryPostProcessor类型的,
// 是BeanFactoryPostProcessor类型的
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors用于调用给定的BeanFactoryPostProcessor类型的Bean。它遍历postProcessors集合,对每个postProcessor执行以下操作:创建一个StartupStep实例来记录bean工厂的后处理步骤,调用postProcessor的postProcessBeanFactory方法来处理bean工厂,结束StartupStep。
/**
* 调用给定的BeanFactoryPostProcessor beans。
*/
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanFactory = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process")
.tag("postProcessor", postProcessor::toString);
postProcessor.postProcessBeanFactory(beanFactory);
postProcessBeanFactory.end();
}
}
4、对beanFactoryPostProcessor中非BeanDefinitionRegistryPostProcessor类型的后处理器进行统一的BeanFactoryPostProcessor的postProcessBeanFactory方法调用。
5、普通beanFactory处理
BeanDefinitionRegistryPostProcessor只对BeanDefinitionRegistry类型的ConfigurableListableBeanFactory有效,所以如果判断所示的beanFactory并不是BeanDefinitionRegistry,那么便可以忽略BeanDefinitionRegistryPostProcessor,而直接处理BeanFactoryPostProcessor,当然获取的方式与上线的获取类似。
这里需要提到的是,对于硬编码方式手动添加的后处理器是不需要做任何排序的,但是在配置文件中读取的处理器,Spring并不保证读取的顺序。所以,为了保证用户的调用顺序的要求,Spring对于后处理器的调用支持按照PriorityOrdered或Ordered的顺序调用。
注册BeanPostProcessor
registerBeanPostProcessors函数的源码如下:
/**
* 实例化和注册所有的 BeanPostProcessor 调整器,
* 如果有明确的顺序则尊重给定的顺序。
* <p>在任何应用程序bean的实例化之前必须调用。
*/
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory)
{
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
上面的方法直接调用PostProcessorRegistrationDelegate的静态方法registerBeanPostProcessors来实现的,源码如下:
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 注册BeanPostProcessor
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// 注册BeanPostProcessorChecker,用于在BeanPostProcessor实例化时记录创建的bean,
// 即在BeanPostProcessor处理之前创建的bean。当Spring的配置中的所有被注册都已经开始了
// bean的初始化时便会打印出BeanPostProcessorChecker设定的信息。
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(
new BeanPostProcessorChecker(beanFactory, postProcessorNames, beanProcessorTargetCount));
// 将BeanPostProcessor按照实现的PriorityOrdered, Ordered和其余的进行分类
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
// 使用Ordered保证顺序
List<String> orderedPostProcessorNames = new ArrayList<>();
// 无序BeanPostProcessor
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 第一步,注册实现PriorityOrdered的BeanPostProcessor
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// 第二步,注册实现Ordered的BeanPostProcessor
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// 第三步,注册所有无序的BeanPostProcessor
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// 第四步,注册所有MergedBeanDefinitionPostProcessor类型的BeanPostProcessor,
// 并非重复注册,在beanFactory.addBeanPostProcessor中会移除已经存在的BeanPostProcessor
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// 将ApplicationListenerDetector重新注册到处理器链的末尾,用于检测内部bean作为ApplicationListener
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
该方法用于注册BeanPostProcessors。它首先获取所有实现BeanPostProcessor类型的处理器的名称,然后注册一个BeanPostProcessorChecker,用于在BeanPostProcessor实例化期间记录创建的bean信息。接着根据处理器实现的PriorityOrdered、Ordered和其他接口进行分类,然后分别注册这些处理器。最后,重新注册所有内部BeanPostProcessor,并将检测内部bean作为ApplicationListeners的处理器移动到处理器链的末尾。
初始化消息资源
在initMessageSource方法中获取自定义资源文件的方式为beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class),在这里Spring使用了硬编码的方式硬性规定了自定义资源文件必须为message,否则便会获取不到自定义资源配置,这也是为什么之前提到Bean的id如果部位message会抛出异常。
/**
* 初始化消息源。
* 如果当前上下文中没有定义消息源,则使用父级消息源。
*/
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// 使消息源知道父级消息源。
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource hms &&
hms.getParentMessageSource() == null) {
// 只有当父级消息源尚未注册时,才将父上下文设置为父级消息源。
hms.setParentMessageSource(getInternalParentMessageSource());
}
if (logger.isTraceEnabled()) {
logger.trace("使用的消息源为 [" + this.messageSource + "]");
}
}
else {
// 使用空消息源以能够接受getMessage调用。
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled()) {
logger.trace("没有'" + MESSAGE_SOURCE_BEAN_NAME + "' bean,使用 [" + this.messageSource + "]");
}
}
}
通过读取并将在自定义资源文件配置记录在容器中,那么就可以在获取资源文件的时候直接使用了。例如,在AbstractApplicationContext中获取资源文件属性的方法:
@Override
public String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException {
return getMessageSource().getMessage(code, args, locale);
}
其中的getMessageSource()方法正是获取了之前定义的自定义资源配置。
初始化ApplicationEventMulticaster
initApplicationEventMulticaster的方法比较简单,无非是考虑两种情况。
- 如果用户自定义了事件广播器,那么使用用户自定义的事件广播器。
- 如果用户没有自定义事件广播器,那么使用默认的ApplicationEventMulticaster
/**
* 初始化 ApplicationEventMulticaster。
* 如果上下文中未定义 ApplicationEventMulticaster,则使用 SimpleApplicationEventMulticaster。
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("使用 ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("没有 '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' 账号,使用 " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
当产生Spring事件的时候会默认使用SimpleApplicationEventMulticaster的multicastEvent方法来广播事件,遍历所有监听器,并使用监听器中的OnApplicationEvent方法进行监听器的处理。而对于每个监听器来说其实都可以获取产生的时间,但是是否进行处理则有事件监听器来决定。
注册监听器
/**
* 添加实现 ApplicationListener 接口的 Bean 作为监听器。
* 不会影响其他监听器,这些监听器可以不通过 Bean 的方式添加。
*/
protected void registerListeners() {
// 首先注册静态指定的监听器。
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 不要在这里初始化 FactoryBeans:我们需要保留所有普通 Bean 未初始化,以便让后处理器应用到它们!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 在我们现在终于有了一个广播器后,立即发布早期应用程序事件...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
初始化非延迟加载单例
完成BeanFactory的初始化工作,其中包括ConversionService的设置、配置冻结以及非延迟加载的bean的初始化工作。
/**
* 完成该上下文的bean工厂的初始化,初始化所有剩余的单例bean。
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 为该上下文初始化转换服务。
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));
}
// 如果没有BeanFactoryPostProcessor(例如PropertySourcesPlaceholderConfigurer bean)在之前进行注册,
// 则注册一个默认的嵌入式值解析器,主要用于解析注解属性值。
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 早期初始化LoadTimeWeaverAware beans,以便早点注册它们的转换器。
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// 停用临时类加载器进行类型匹配。
beanFactory.setTempClassLoader(null);
// 允许缓存所有的bean定义元数据,不期望还有进一步的变化。
beanFactory.freezeConfiguration();
// 实例化所有剩余的(非懒加载)单例bean。
beanFactory.preInstantiateSingletons();
}
这个函数用于完成该上下文的bean工厂的初始化,包括初始化所有剩余的单例bean。首先,它会初始化转换服务,然后注册一个默认的嵌入式值解析器。接下来,它会早期初始化LoadTimeWeaverAware beans,以便注册它们的转换器。然后,它会停止使用临时类加载器进行类型匹配,并允许缓存所有的bean定义元数据。最后,它会实例化所有剩余的非懒加载单例bean。
finishRefresh
在Spring中还提供了Lifecycle接口,Lifecycle中包含了start/stop方法,实现此接口后Spring会保证在启动的时候调用start方法开始生命周期,并在Spring关闭的时候调用stop方法来结束生命周期,通常用来配置后台程序,在启动后一直运行(例如对MQ进行轮询等)。而ApplicationContext的初始化最后正是保证了这一功能的实现。
/**
* 完成刷新操作,调用LifecycleProcessor的onRefresh()方法,并发布
* org.springframework.context.event.ContextRefreshedEvent事件。
*/
protected void finishRefresh() {
// 重置Spring核心基础设施中的常用反射缓存。
resetCommonCaches();
// 清除上下文级别的资源缓存(例如扫描时的ASM元数据)。
clearResourceCaches();
// 初始化上下文的生命周期处理器。
initLifecycleProcessor();
// 首先将刷新操作传递给生命周期处理器。
getLifecycleProcessor().onRefresh();
// 发布最终事件。
publishEvent(new ContextRefreshedEvent(this));
}
这个函数用于完成上下文的刷新操作,调用LifecycleProcessor的onRefresh()方法,并发布ContextRefreshedEvent事件。在刷新过程中,会重置Spring核心基础设施中的常用反射缓存,清除上下文级别的资源缓存,初始化上下文的生命周期处理器,并将刷新操作传递给生命周期处理器。最后,会发布刷新完成的事件。
initLifecycleProcessor
当ApplicationContext启动或停止时,它会通过LifecycleProcessor来与所有生命的bean的周期做状态更新,而在LifecycleProcessor的使用前需要初始化。
/**
* 初始化LifecycleProcessor。
* 如果上下文中没有定义,则使用DefaultLifecycleProcessor。
* @see org.springframework.context.support.DefaultLifecycleProcessor
*/
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isTraceEnabled()) {
logger.trace("使用LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
}
else {
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isTraceEnabled()) {
logger.trace("没有'" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean,使用 " +
"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
}
}
}
onRefresh
启动所有实现了Lifecycle接口的bean。
@Override
public void onRefresh() {
// 刷新事件触发时执行的操作
if (checkpointOnRefresh) {
// 如果设置了在刷新事件触发时进行检查点恢复
new CracDelegate().checkpointRestore();
}
if (exitOnRefresh) {
// 如果设置了在刷新事件触发时退出
Runtime.getRuntime().halt(0);
}
this.stoppedBeans = null;
try {
// 尝试启动已经停止的bean
startBeans(true);
}
catch (ApplicationContextException ex) {
// 在上下文刷新过程中,某些bean未能自动启动:
// 刷新失败时停止已经启动的bean
stopBeans();
throw ex;
}
this.running = true;
}
/**
* 启动Bean
* @param autoStartupOnly 是否仅启动自动启动候选 Bean
*/
private void startBeans(boolean autoStartupOnly) {
// 获取生命周期 Bean 的 Map
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
// 创建排序的阶段 Map
Map<Integer, LifecycleGroup> phases = new TreeMap<>();
// 遍历生命周期 Bean 的 Map
lifecycleBeans.forEach((beanName, bean) -> {
// 如果不是仅启动自动启动候选 Bean,或者该 Bean 是自动启动候选 Bean
if (!autoStartupOnly || isAutoStartupCandidate(beanName, bean)) {
// 获取 Bean 的阶段
int phase = getPhase(bean);
// 根据阶段添加 Bean 到对应的 LifecycleGroup 中
phases.computeIfAbsent(
phase,
p -> new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly)
).add(beanName, bean);
}
});
// 如果有阶段
if (!phases.isEmpty()) {
// 遍历阶段的 Map,并启动每个阶段中的 Bean
phases.values().forEach(LifecycleGroup::start);
}
}
publishEvent
当完成ApplicationContext初始化的时候,要通过Spring中的事件发布机制来发出ContextRefreshedEvent事件,以保证对应的监听器可以做进一步的逻辑处理。
/**
* 将给定的事件发布给所有的监听器。
* <p>注意:监听器在MessageSource之后进行初始化,以便在监听器实现中访问它。
* 因此,MessageSource实现不能发布事件。
* @param event 要发布的事件(可以是应用程序特定的或标准框架事件)
*/
@Override
public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
}
/**
* 将给定的事件发布给所有的监听器。
* <p>此方法是其他所有`publishEvent`方法都引用的内部委托方法。它不是用来直接调用的,而是作为层次结构中应用程序上下文之间的传播机制,
* 可能在子类中被重写以实现自定义的传播方式。
* @param event 要发布的事件(可以是{@link ApplicationEvent}或要转换为{@link PayloadApplicationEvent}的有效载荷对象)
* @param typeHint 知晓的解析事件类型。此方法的实现也容许载荷类型提示用于要转换为{@link PayloadApplicationEvent}的载荷对象。
* 但是,建议的方式是通过{@link PayloadApplicationEvent#PayloadApplicationEvent(Object, Object, ResolvableType)}构造一个实际的事件对象。
* @since 4.2
* @see ApplicationEventMulticaster#multicastEvent(ApplicationEvent, ResolvableType)
*/
protected void publishEvent(Object event, @Nullable ResolvableType typeHint) {
Assert.notNull(event, "Event must not be null");
ResolvableType eventType = null;
// 将事件装饰为ApplicationEvent,如果需要的话
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent applEvent) {
applicationEvent = applEvent;
eventType = typeHint;
}
else {
ResolvableType payloadType = null;
if (typeHint != null && ApplicationEvent.class.isAssignableFrom(typeHint.toClass())) {
eventType = typeHint;
}
else {
payloadType = typeHint;
}
applicationEvent = new PayloadApplicationEvent<>(this, event, payloadType);
}
// 只确定一次事件类型(用于广播和父级发布)
if (eventType == null) {
eventType = ResolvableType.forInstance(applicationEvent);
if (typeHint == null) {
typeHint = eventType;
}
}
// 如果可能的话,立即广播(或者在多播器初始化后懒惰广播)
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else if (this.applicationEventMulticaster != null) {
this.applicationEventMulticaster.multicastEvent(applicationEvent, eventType);
}
// 通过父级上下文发布事件...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext abstractApplicationContext) {
abstractApplicationContext.publishEvent(event, typeHint);
}
else {
this.parent.publishEvent(event);
}
}
}