Spring源码阅读一
引导:
众所周知,阅读spring源码最开始的就是去了解spring bean的生命周期:bean的生命周期是怎么样的呢,见图知意:
大致流程:
- 首先后通过BeanDefinitionReader读取xml、注解的Bean定义信息,可以通过
ClassPathXmlApplicationContext
进行配置文件的路径读取。 - 设置好路径之后,便可以根据路径进行配置文件的解析以及各种功能的实现,注解的解析工作通过
BeanFactoryPostProcessor
进行的扩展实现,两者主要在refresh()
方法中完成。 - 然后在创建对象的过程中进行了相关的扩展(后面再详细说明)
源码解读:
如何读取XML配置文件,配置文件路径的设置:
首先,我们回顾一下以前我们加载Bean的时候通常会以BeanFactory
接口以及它的默认实现类XmlBeanFactory
;
注意:
在Spring3.1以后XmlBeanFactory类被废除了
XmlBeanFactory废弃原因
- XmlBeanFactory对作用于的支持单一 BeanFactory只支持两个作用域——Singleton和Prototype。
- XmlBeanFactory延迟加载 在企业及的项目当中,我们对bean的需求往往是比较大的,如果了解延迟加载的朋友,想必了解,延迟加载确实会给我们启动释放很多的压力,但是当我们在运行的时候,大量加载的时候,也会出现性能瓶颈
- XmlBeanFactory不会自动注册接口。后面会有讲到
- XmlBeanFactory在企业级项目里面,并没有太好的支持
但其实在spring中还提供了一个接口ApplicationContext
,用于扩展BeanFactory现有的功能。
ApplicationContext
和BeanFactory
都是用来加载Bean的,但是相比之下,ApplicationContext提供了更多的扩展功能,建议优先使用,而且目前主要使用的也是它,几乎不存在使用XmlBeanFactory的了,但是相关知识还是要了解以下的。但是也有例外情况:比如字节长度对内存有很大影响时(Applet),绝大多数的企业级应用系统,都是使用ApplicationContext,那么究竟扩展了哪些功能呢?首先我们先看一下两种方式的写法:
@Test
public void Test(){
//使用BeanFactory方式加载XML.
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
}
@Test
void TestPostProcessor(){
//使用ApplicationContext方式加载XML.
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("postProcessor.xml");
}
接下来我们以ClassPathXmlApplicationContext
为切入点来进行分析:
- 看源码(
ClassPathXmlApplicationContext.class
):
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
@Nullable
private Resource[] configResources;
public ClassPathXmlApplicationContext() {
}
public ClassPathXmlApplicationContext(ApplicationContext parent) {
super(parent);
}
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
this(configLocations, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, @Nullable ApplicationContext parent)
throws BeansException {
this(configLocations, true, parent);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
this(configLocations, refresh, null);
}
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
// 支持多个文件以数组方式传入
setConfigLocations(configLocations);
if (refresh) {
// refresh函数几乎包含了applicationContext中提供的所有功能
refresh();
}
}
public ClassPathXmlApplicationContext(String path, Class<?> clazz) throws BeansException {
this(new String[] {path}, clazz);
}
public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz) throws BeansException {
this(paths, clazz, null);
}
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()
方法实现了配置文件的解析功能。
支持多个配置文件以数组方式传入的源代码块:
setConfigLocations(configLocations);
带你进去查看该方法的实现(这里还对路径中的特殊字符进行了解析通过resolvePath()
方法):
public void setConfigLocations(@Nullable String... locations) {
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
// 如果给定的路径中包含特殊符号,如${var},那么会在方法resolvePath中解析系统变量并替换
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
配置文件的解析及其他功能的实现:
上述已经提到配置文件的解析以及各种功能的实现包含在了refresh()
方法中,也可以说该方法包含了ApplicationContext
几乎全部的功能。源码中也比较清楚的进行了呈现:
- 看源码(具体实现在
AbstractApplicationContext.class
):
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
// 1.准备刷新的上下文 环境
prepareRefresh();
// 2.初始化beanFactory 并进行xml文件读取
//ClassPathXmlApplicationContext 包含着beanFactory所提供的一切特征,在这一步会将复用
//BeanFactory中的配置文件读取解析及其他功能,这一步之后
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3.对beanFactory的各种功能进行填充 、BeanFactory的预准备工作
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// 4.子类覆盖方法做额外处理 (具体的见 AbstractRefreshableWebApplicationContext 类中)
/*
BeanFactory的预准备工作(BeanFactory进行一些设置)
* spring 之所以强大,为世人所推崇,除了它功能上为大家提供便利外,还因为它很好的架构,开放式的架构让使用它的程序员根据业务需要
* 扩展已经存在的功能,
* 这种开放式的设计spring随处可见,例如在本例中提供了空的函数实现postProcessBeanFactory 方便程序猿在业务上做进一步扩展 */
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
/* 5.激活beanFactory的处理器 (Bean的后置处理器)
* ===========详解=========
* BeanFactoryPostProcessor 接口和 BeanFactoryProcessor 类似,都可以对bean定义(配置元数据)进行处理,也就是说SpringIOC允许
* BeanFactoryPostProcessor 在容器实际实例化任何其他的bean之前来读取配置元数据,并可能修改它,也可以配置多个BeanFactoryPostProcessor
* ,可以通过order属性来控制BeanFactoryPostProcessor的执行顺序(注意:此属性必须当BeanFactoryPostProcessor实现了Ordered
* 接口时才可以赊账),因此在实现BeanFactoryPostProcessor时应该考虑实现Ordered接口
* 如果想改变实现的bean实例(例如从配置源数据创建的对象),那最好使用BeanPostProcessor,同样的BeanFactoryPostProcessor,
* 的作用域范围是容器级别的,它只是和你锁使用的容器有关。如果你在容器中定义了一个BeanFactoryPostProcessor,它仅仅对此容器的
* bean进行后置处理,BeanFactoryPostProcessor不会对定义在另外一个容器的bean进行后置处理,即使两个容器都在同一个层次上。
* 在spring中存在对BeanFactoryPostProcessor的典型应用,如:PropertyPlaceholderConfigure
* */
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// 6.注册拦截Bean创建的Bean拦截器(Bean的后置处理器,拦截Bean的创建),这里只是注册,真正调用的时候 是在getBean
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 7.为上下文处理Message源,国际化处理 即不同语言的消息体
// Initialize message source for this context.
initMessageSource();
// 8.初始化应用消息广播器 也就是事件派发器,并放入 ApplicationEventMulticaster 中
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// 9.留给子类来初始化它的Bean 给子容器(子类),子类重写这个方法,在容器刷新的时候可以自定义逻辑
// Initialize other special beans in specific context subclasses.
onRefresh();
// 10.在所有注册的Bean中查找Listener Bean 注册到广播器中
// Check for listener beans and register them.
registerListeners();
// 初始化剩下的单实例(非惰性的)
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// 最后一步完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出 ContentRefreshEvent 通知别人
// Last step: publish corresponding event.
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...
resetCommonCaches();
contextRefresh.end();
}
}
}
- 源码分析:
简单分析一下代码的步骤:
初始化准备前的工作:
例如对系统属性和环境变量进行验证,在某种情况下项目的使用需要读取系统的环境变量,而这个系统变量的设置可能会影响系统的正确性,那么ClassPathXmlApplicationContext为我们提供的准备函数就显得十分重要,它可以在spring启动的时候提前对必须的环境变量进行存在性验证。
初始化BeanFactory并进行XML文件读取:
之前提到ClassPathXmlApplicationContext包含着对BeanFactory所提供的一切特征。那么这一步将会复用BeanFactory中的配置文件读取解析其他功能;这一步之后其实ClassPathXMLApplicationContext就已经包含了BeanFactory所提供的功能,也就是可以进行Bean的提取等基本操作了。
对BeanFactory进行各种功能扩充:
@Qualifier、@Autowired应该是大家非常熟悉的注解了。那么这一注解正是对这一步骤增加支持的。
子类覆盖方法做额外处理
spring之所以强大,为世人所推崇,除了它功能上为大家提供了遍历外,还有一方面是它完美的架构,开放式的架构让使用它的程序员很容易根据业务需要扩展已经存在的功能。这种开放式的设计在spring中随处可见,例如本利中就提供了一个空的函数实现postProcessBeanFactory来方便程序员在业务上做进一步的扩展
激活各种BeanFactory处理器 (后置处理器)
注册Bean创建的Bean处理器,这里只是创建,真正调用在getBean()
为上下文处理Message源 国际化处理,及不同消息体
注册应用消息广播器。并放入ApplicationEventMulticaster中
留给子类来初始话其他类,也就是子类重写这个方法,在容器刷新的时候自定义逻辑
在所有注册的Bean中找到Listener Bean 注册到消息广播中
初始化剩下的单实例(非惰性的)
最后一步:通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人
接下来针对以上步骤的详解:
详解refresh()
函数
prepareRefresh() 刷新上下文的准备工作:
- 看源码(具体实现在
AbstractApplicationContext.class
)
/**
* 准备刷新上下文环境,设置他的启动日期和活动标志,以及执行任何属性源的初始化
*/
protected void prepareRefresh() {
// Switch to active.
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());
}
}
// 在上下文环境中初始化任何占位符属性源 (空的方法 留给子类覆盖)
initPropertySources();
// 验证需要的属性文件是否都已放入环境中
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
// 存储容器预刷新的 ApplicationListeners
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...
// 允许收集早期的应用程序事件,一旦有了多播器,就可以发布……
this.earlyApplicationEvents = new LinkedHashSet<>();
}
- 源码解读(看上面的注释)
obtainFreshBeanFactory() 读取XML初始化BeanFactory
- 看源码(具体实现在
AbstractApplicationContext.class
)
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
/*初始化BeanFactory,并进行XML文件读取 并将得到的BeanFactory记录在当前实体的属性中
* 进入到该方法 refreshBeanFactory():方法的实现是在 AbstractRefreshableApplicationContext 中
* */
refreshBeanFactory();
// 返回当前BeanFactory的属性
return getBeanFactory();
}
- 源码分析
obtainFreshBeanFactory方法的字面意思是获取beanFactory.ApplicationContext是对BeanFactory的扩展,在其基础上添加了大量的基础应用obtainFreshBeanFactory()方法是正式实现BeanFactory
的地方,经此之后ApplicationContext就有了BeanFactory的全部功能
继续深入到方法obtainFreshBeanFactory()中的refreshBeanFactory方法中
- 看源码(具体实现在
AbstractRefreshableApplicationContext.class
)
@Override
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
/* 1.创建DefaultListableBeanFactory*/
/* 以前我们分析BeanFactory的时候,不知道是否还有印象,声明方式为:BeanFactory bf = new XmlBeanFactory("beanFactoryTest.xml")
* 其中XmlBeanFactory继承自DefaultListableBeanFactory,并提供了XmlBeanDefinitionReader类型的 reader属性,也就是说
* DefaultListableBeanFactory是容器的基础 必须首先要实例化。
* */
DefaultListableBeanFactory beanFactory = createBeanFactory();
/* 2.为了序列化指定id 如果需要的话让这个BeanFactory从这个id反序列化到BeanFactory对象*/
beanFactory.setSerializationId(getId());
/* 3.自定义BeanFactory,设置相关属性 包括是否允许覆盖同名称的不同定义的对象以及循环依赖 以及设置@Autowired和@Qualifier注解解析器
* QualifierAnnotationAutowireCandidateResolver
* */
customizeBeanFactory(beanFactory);
/* 4.加载BeanDefinition
* */
loadBeanDefinitions(beanFactory);
// 5.使用全局变量记录BeanFactory实例 因为DefaultListableBeanFactory类型的变量beanFactory是函数内部的局部变量 所以要使用全局变量记录解析结果
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
- 源码分析:
在这一步中将ClassPathXmlApplicationContext
与XmlBeanFactory
进行对比。除了初始化DefaultListableBeanFactory
外,还需要XmlBeanDefinitionReader
来读取XML,那么在loadBeanDefinitions
中首先要做的就是初始化XmlBeanDefinitionReader
,然后我们接着到loadBeanDefinitions(beanFactory)方法体中。
加载BeanDefinition
- 看源码(具体是现在
AbstractXmlApplicationContext.class
)
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}
- 源码分析
上述refreshBeanFactory方法和 loadBeanDefinitions方法初始化了DefaultListableBeanFactory
和XmlBeanDefinitionReader
后就可以进行配置文件的解析了,继续进入到loadBeanDefinitions(beanDefinitionReader)
方法体中
- 看源码(具体是现在
AbstractXmlApplicationContext。class
)
/**
* 因为在 XmlBeanDefinitionReader 中已经将之前初始化的 DefaultListableBeanFactory 注册进去了,所以 XmlBeanDefinitionReader
* 所读取的 BeanDefinitionHolder 都会注册到 DefinitionListableBeanFactory 中,也就是经过这个步骤,DefaultListableBeanFactory
* 的变量beanFactory 已经包含了所有解析好的配置
*/
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
中已将初始化好的DefaultListableBeanFactory
注册进去了,所以XmlBeanDefinitionReader所读取的BeanDefinitionHolder
都会注册到DefaultListableBeanFactory中去,也就是经过这个步骤,DefaultListableBeanFactory的变量beanFactory已经包含了所有解析好的配置。
prepareBeanFactory(beanFactory) 对beanFactory的各种功能进行填充
在这个方法之前spring已经完成了对配置的解析,接下来就是扩展功能,让我们进入方法体:
- 看源码(具体实现在
AbstractApplicationContext.class
)
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置beanFactory的classLoader为当前context的classloader
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
//设置beanFactory的表达式语言处理器,Spring3增加了表达式语言的支持,
//默认可以使用#{bean.xxx}的形式来调用相关属性值
if (!shouldIgnoreSpel) {
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
//为beanFactory增加了一个的propertyEditor,这个主要是对bean的属性等设置管理的一个工具
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
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 interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
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));
// 增加对AspectJ的支持
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!NativeDetector.inNativeImage() && 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()));
}
// 添加默认的系统环境bean
// Register default environment beans.
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());
}
/* 总结:
* 对SpEL语言进行了支持
* 增加对SpEL语言的支持
* Spring表达式语言全称为“Spring Expression Language”,缩写为“SpEL”,类似于Struts 2x中使用的OGNL语言,SpEL是单独模块,
* 只依赖于core模块,不依赖于其他模块,可以单独使用。SpEL使用#{…}作为定界符,所有在大框号中的字符都将被认为是SpEL
* 增加属性编辑器的支持
* 增加一些内置类的支持,如:EnvironmentAware、MessageSourceAware的注入
* 设计依赖功能可忽略的端口
* 注册了一些固定的依赖属性
* 增加了AspectJ的支持
* 将相关环境变量及属性以单例模式注册
* */
}
- 源码分析
总结上面函数里的方法具体做了哪些扩展
- 对SpEL语言的支持
- 增加对属性编辑器的支持
- 增加一些内置类的支持(如EnvironmentAware、MessageSourceAware的注入)
- 设置了依赖功能可忽略的接口
- 注册一些固定依赖属性
- 增加AspectJ的支持
- 将相关环境变量及属性以单例模式注册
SpEL语言支持的讲解:
Spring表达式语言全称为Spring Expression Language
,缩写为SpEL
,和Struts2中的OGNL
语言比较相似。
并且SpEL
是单独的模块,只依赖于core
模块,不再依赖其它任何模块,可以单独使用。SpEL使用#{...}
作为定界符,所有在大框号中的字符都将被认为是SpEL,使用格式如下:
<util:properties id="database" location="classpath:db.properties">
</util:properties>
<bean id="dbcp" class="org.apache.commons.dbcp.BasicDataSource">
<property name="username" value="#{database.user}"></property>
<property name="password" value="#{database.pwd}"></property>
<property name="driverClassName" value="#{database.driver}"></property>
<property name="url" value="#{database.url}"></property>
</bean>
以上只是简单的列举使用方式,SpEL不仅如此,非常强大;在spring源码中通过beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()))
注册语言解析器。上述的prepareBeanFactory(beanFactory)
中有提到。
**那么问题来了,之后又是在什么地方调用的的这个解析器呢?**
之前有在beanFactory中说过Spring在bean进行初始化的时候会有属性填充的一步,而在这一步中Spring会调用AbstractAutowireCapableBeanFactory
类中的applyPropertyValue
来进行属性值解析。同时这个步骤一般通过AbstractBeanFactory
中的evaluateBeanDefinitionString
方法进行SpEL解析。源代码如下:
/**
* 进行SpEL解析
*/
/**
* Evaluate the given String as contained in a bean definition,
* potentially resolving it as an expression.
* @param value the value to check
* @param beanDefinition the bean definition that the value comes from
* @return the resolved value
* @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));
}
BeanFactory的后置处理器
BeanFactory作为spring中容器功能的基础,用于存放所有已经加载的bean,为保证程序上的高扩展性,spring对BeanFactory做了大量扩展,比如我们熟知的PostProcessor就是在这里实现的,接下来我们就详细的分析下BeanFactory的后处理
激活注册的BeanFactoryPostProcessor
说说BeanFactoryPostProcessor的后处理前,说之前我们先大概了解一下它的用法,BeanFactoryPostProcessor
和BeanPostProcessor
类似,都可以对bean的定义(元数据)进行修改,也就是说Spring IOC
允许BeanFactoryPostProcessor在容器实例化任何其他的bean之前读取配置元数据,并进行修改,也可以配置多个BeanFactoryPostProcessor,可以通过order
属性来控制BeanFactoryPostProcessor
的执行顺序(此属性必须当BeanFactoryPostProcessor实现Ordered
接口时才可以赊账)。因此在实现BeanFactoryPostProcessor时可以考虑实现Ordered接口。
如果想要改变bean实例(例如从配置元数据创建的对象),那么最好使用`BeanPostProcessor`,因为`BeanFactoryPostProcessor的作用域范围是容器级别的`,它只是和你所使用的容器有关;如果你再容器中定义了一个BeanFactoryPostProcessor,意味着它也就只能对此容器中的bean进行处理,BeanFactoryPostProcessor不会对另外一个容器中的bean进行后处理,即使两个容器在同一级别上。
由上述可得BeanFactoryPostProcessor
和BeanPostProcessor
的区别:
BeanFactoryPostProcessor的作用域范围是容器级别的
在spring中对BeanFactoryProcessor的典型应用,如:`PropertyPlaceHolderConfigurer`
BeanFactoryPostProcessor的典型应用:PropertyPlaceholderConfigurer
有时候我们在阅读spring的配置文件中的Bean的描述时,会遇到类似如下的情况:
<bean id="user" class="com.vipbbo.spring.Bean.User">
<property name="name" value="${user.name}"/>
<property name="birthday" value="${user.birthday"/>
</bean>
这其中出现了变量user.name、user.birthday,这是spring的分散配置,可以在spring中其他的配置文件中为这两个变量设置属性值,例如:在bean.properties
中
user.name = paidaxing
user.birthday = 2021-09-23
重点来了:
当访问名为user的bean时,其name属性值就会被bean.properties中的paidaxing替换掉,那么spring是如何知道这个配置文件的存在呢?这就要说到PropertyPlaceHolderConfigurer
了。在配置文件中添加如下代码:
<bean id="userHandler" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:bean.properties</value>
</list>
</property>
</bean>
在这个bean标签中指定了配置文件的位置,其实还有一个问题?这个userHandler只不过是spring框架中管理的一个bean,并没有被别的bean或对象引用,spring中的banFactory是如何知道从这个配置文件中读取属性值的呢,接下我们就需要看一下PropertyPlaceHolderConfigurer
这个类的层次结构:
在上图中我们不难发现PropertyPlaceHolderConfigurer间接的继承了BeanFactoryPostProcessor
接口,这是一个很特别的接口,当spring加载任何实现了这个接口的bean的配置信息时,都会在bean工厂载入所有的配置之后执行postProcessorBeanFactory
方法。在PropertyResourceConfigurer
类中实现了postProcessorBeanFactory
方法,在方法中先后调用了mergeProperties
、convertProperties
、processProperties
这三个方法,分别得到配置,将得到的配置转换为合适的类型,最后将配置内容告知BeanFactory
。
源码如下;
/**
* {@linkplain #mergeProperties Merge}, {@linkplain #convertProperties convert} and
* {@linkplain #processProperties process} properties against the given bean factory.
* @throws BeanInitializationException if any properties cannot be loaded
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
try {
Properties mergedProps = mergeProperties();
// Convert the merged properties, if necessary.
convertProperties(mergedProps);
// Let the subclass process the properties.
processProperties(beanFactory, mergedProps);
}
catch (IOException ex) {
throw new BeanInitializationException("Could not load properties", ex);
}
}
正是通过实现BeanFactoryPostProcessor接口,BeanFactory会在实例化任何bean之前获取到配置信息,从而能够正确的解析bean描述文件中的变量引用。
注意:
在spring5.2中弃用了
PropertyPlaceholderConfigurer
使用org.springframework.context.support.PropertySourcesPlaceholderConfigurer通过利用org.springframework.core.env.Environment和org.springframework.core.env.PropertySource机制更加灵活
但是官方也依旧说明在一些地方它可以继续使用
PlaceholderConfigurerSupport subclass that resolves ${...} placeholders against local properties and/or system properties and environment variables. PropertyPlaceholderConfigurer is still appropriate for use when: the spring-context module is not available (i.e., one is using Spring's BeanFactory API as opposed to ApplicationContext). existing configuration makes use of the "systemPropertiesMode" and/or "systemPropertiesModeName" properties. Users are encouraged to move away from using these settings, and rather configure property source search order through the container's Environment; however, exact preservation of functionality may be maintained by continuing to use PropertyPlaceholderConfigurer. Deprecated as of 5.2; use org.springframework.context.support.PropertySourcesPlaceholderConfigurer instead which is more flexible through taking advantage of the org.springframework.core.env.Environment and org.springframework.core.env.PropertySource mechanisms. Since: 02.10.2003 See Also: setSystemPropertiesModeName, PlaceholderConfigurerSupport, PropertyOverrideConfigurer
invokeBeanFactoryPostProcessor 子类覆盖方法做额外处理
自定义BeanFactoryPostProcessor 也就是扩展功能
编写一个实现BeanFactoryPostProcessor接口的MyBeanFactoryPostProcessor
代码如下:
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("对容器进行后处理。。。。");
}
然后在配置文件中注册这个bean,如下:
<bean id="myPost" class="com.vipbbo.spring.applicationcontext.MyBeanFactoryPostProcessor"></bean>
最后编写测试代码:
@Test
public void TestPostProcessor2_2(){
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("postProcessor2.xml");
User user = (User) applicationContext.getBean("user");
System.out.println(user.getName());
}
激活BeanFactoryPostProcessor的调用过程
以上我们了解了BeanFactoryPostProcess的用法,接下来我们继续看一下它的调用过程了。**其实是在方法`invokeBeanFactoryPostProcessor(beanFactory)`中实现的**,我们进入到方法内部:
- 看源码(具体实现在
PostProcessorRegistrationDelegate.class
):
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 1、首先调用 BeanDefinitionRegistryPostProcessors
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
// beanFactory是 BeanDefinitionRegistry 类型
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 定义BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// 定义BeanDefinitionRegistryPostProcessor集合
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 循环手动注册的 beanFactoryPostProcessors
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
/* 如果是BeanDefinitionRegistryPostProcessor的实例话,
* 则调用其 postProcessBeanDefinitionRegistry 方法,对bean进行注册操作
*/
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
// 否则则将其当做普通的BeanFactoryPostProcessor处理,直接加入regularPostProcessors集合,以备后续处理
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 首先调用实现了 PriorityOrdered (有限排序接口)的
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
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));
processedBeans.add(ppName);
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 加入registryProcessors集合
registryProcessors.addAll(currentRegistryProcessors);
// 调用所有实现了PriorityOrdered的的BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry方法,注册bean
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
// 清空currentRegistryProcessors,以备下次使用
currentRegistryProcessors.clear();
// 其次,调用实现了Ordered(普通排序接口)的BeanDefinitionRegistryPostProcessors
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
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));
processedBeans.add(ppName);
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 加入registryProcessors集合
registryProcessors.addAll(currentRegistryProcessors);
// 调用所有实现了PriorityOrdered的的BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry方法,注册bean
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
// 清空currentRegistryProcessors,以备下次使用
currentRegistryProcessors.clear();
// 最后,调用其他的BeanDefinitionRegistryPostProcessors
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
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));
processedBeans.add(ppName);
reiterate = true;
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 加入registryProcessors集合
registryProcessors.addAll(currentRegistryProcessors);
// 调用其他的 BeanDefinitionRegistryProcessors 的 postProcessorBeanDefinitionRegistry 方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
// 清空currentRegistryProcessors集合 以供下次使用
currentRegistryProcessors.clear();
}
/* 现在调用所有的 BeanDefinitionRegistryPostProcessor (包括手动注册和配置文件注册) 和
* 和 BeanFactoryPostProcessor(只有手动注册)的回调函数 -> postProcessBeanFactory
*/
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
// 2.如果不是BeanDefinitionRegistry的实例,那么直接调用其他回调函数即可 -->postProcessBeanFactory
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 上面的代码已经处理完了所有的 BeanDefinitionRegistryPostProcessor 和 手动注册的 BeanFactoryPostProcessor
// 接下来要处理通过配置文件注册的 BeanFactoryPostProcessor
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// 首先获取所有的BeanFactoryPostProcessor (注意:这里获取的集合会包含 BeanDefinitionRegistryPostProcessors)
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 这里 将实现了 PriorityOrdered Ordered的处理器和其他处理器区分开来,分别进行处理
// PriorityOrdered有序处理器
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
// Ordered有序处理器
List<String> orderedPostProcessorNames = new ArrayList<>();
// 无序处理器
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// 判断processedBeans是否包含当前处理器(processedBeans中的处理器已经处理过的 也就是上边第一步已经处理过的),如果包含则不做处理
// skip - already processed in first phase above
}
// 加入到PriorityOrdered有序处理器集合
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
// 加入到Ordered有序处理器集合
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
// 加入到无序处理器集合
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 首先调用实现了 PriorityOrdered 接口的处理器
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 其次 调用了 Ordered 接口的处理器
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 最后 调用了无序处理器
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
// 循环遍历 BeanFactoryPostProcessor 中的 postProcessBeanFactory 方法
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// 清理元数据
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
循环遍历 BeanFactoryPostProcessor 中的 postProcessBeanFactory 方法
- 看源码
/**
* Invoke the given 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();
}
}
注册BeanPostProcessor
上面讲了`BeanFactoryPostProcessor`的调用过程,接下来我们看一下和它类似的`BeanPostProcessor`,**但这里不是调用,注意不是调用是注册 、注册、注册**,真正的调用其实是在bean的实例化阶段进行的,这是一个很重要的步骤,也是很多功能`BeanFactory`不知道的原因。所以在调用的时候如果没有进行手动注册其实是不能使用的,**但是`ApplicationContext`中却添加了自动注册的功能**,如自定义一个后置处理器:
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
// return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
System.out.println("before");
return null;
}
}
然后再配置文件中添加bean的配置
<bean id="myInstantiationAwareBeanPostProcessor" class="com.vipbbo.spring.applicationcontext.MyInstantiationAwareBeanPostProcessor">
</bean>
这样配置之后写一个测试类:
@Test
public void TestPostProcessor2_1(){
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("postProcessor2.xml"));
User user = (User) beanFactory.getBean("user");
System.out.println(user.getName());
}
@Test
public void TestPostProcessor2_2(){
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("postProcessor2.xml");
User user = (User) applicationContext.getBean("user");
System.out.println(user.getName());
}
运行完测试类我们不难发现在使用BeanFactory
的方式进行加载的bean在加载的过程中是不会有任何改变的。而在使用ApplicationContext
方式获取的bean信息的过程中就会打印出我们在自定义后置处理器中所打印的【before】 ,问题来了这个操作是在那里完成的呢,其实这个特性就是在refresh方法中的registryBeanPostProcessor
方法中完成的。我们来看一下该方法的具体实现:
- 看源码(具体实现在
PostProcessorRegistrationDelegate.class
)
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// WARNING: Although it may appear that the body of this method can be easily
// refactored to avoid the use of multiple loops and multiple lists, the use
// of multiple lists and multiple passes over the names of processors is
// intentional. We must ensure that we honor the contracts for PriorityOrdered
// and Ordered processors. Specifically, we must NOT cause processors to be
// instantiated (via getBean() invocations) or registered in the ApplicationContext
// in the wrong order.
//
// Before submitting a pull request (PR) to change this method, please review the
// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
// to ensure that your proposal does not result in a breaking change:
// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
/**
* BeanPostProcessorChecker 是一个普通的信息打印,可能会有些情况当spring的配置中的后置处理器还没有被注册就已经开始了bean的初始化
* 这时就会打印出BeanPostProcessorChecker中设定的信息
*/
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 使用PriorityOrdered来保证顺序
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
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
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// 注册了所有实现Ordered 的 BeanPostProcessor
// Next, register the BeanPostProcessors that implement Ordered.
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
// Now, register all regular BeanPostProcessors.
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);
// 组后 注册所有内部 BeanPostProcessor
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// 添加 ApplicationListener探测器
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
- 源码分析:
我们可以看到先从容器中获取了所有类型为BeanPostProcessor.class 的Bean的name数组,然后通过BeanPostProcessor pp = beanFactory.getBean(ppName,BeanPostProcessor.class)
获取到实例,最后通过registerBeanPostProcessor(beanFactory,OrderedPostProcessor)
将获取到的BeanPostProcessor
实例添加到容器属性中,如下:
/**
* Register the given BeanPostProcessor beans.
*/
private static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
if (beanFactory instanceof AbstractBeanFactory) {
// Bulk addition is more efficient against our CopyOnWriteArrayList there
((AbstractBeanFactory) beanFactory).addBeanPostProcessors(postProcessors);
}
else {
for (BeanPostProcessor postProcessor : postProcessors) {
beanFactory.addBeanPostProcessor(postProcessor);
}
}
}
真正将BeanPostProcessor加入到容器属性中的是 registerBeanPostProcessors 方法中的addBeanPostProcessor
,addBeanPostProcessor方法的具体实现是在AbstractBeanFactory
中
- 看源码
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// Remove from old position, if any
this.beanPostProcessors.remove(beanPostProcessor);
// Add to end of list
this.beanPostProcessors.add(beanPostProcessor);
}
在这里可以看到将 beanPostProcessor 实例添加到容器的 beanPostProcessors 属性中
初始化Message资源
此处暂时省略 。。。。。。。。。。。。。。。。。。。。。
initApplicationEventMulticaster 初始化广播器
这里直接
- 看源码(具体实现在
AbstractApplicationContext.class
)
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 默认使用内置的事件广播器; 如果有的话,我们可以在配置文件中配置Spring的事件广播器或自定义事件广播器
// 例如:
/**
* <bean id="simpleApplicationEventMulticaster" class="org.springframework.context.event.SimpleApplicationEventMulticaster">
* </bean>
*/
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
// 否则新建一个事件广播器,SimpleApplicationEventMulticaster是spring的默认事件广播器
else {
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() + "]");
}
}
}
通过源码可以看到其相关逻辑,initMessageSource()的逻辑与其大致相同,有兴趣的可以按照这个逻辑去看一下初始化Message源的相关代码,回到正题`initApplicationEventMulticaster `的步骤如下
- 查找是否由name为applicationListener的bean,如果有则放到容器中,如果没有则初始化一个系统默认的
SimpleApplicationEventMulticaster
放到容器 - 查找手动设置的applicationListeners,添加到applicationEventMulticaster里
- 查找定义类型为ApplicationListener的bean,设置到applicationEventMulticaster
- 初始化完成,对
earlyApplicationEvents
里的事件进行通知(此容器仅仅是广播器未建立的时候保存通知信息,一旦容器建立完成,以后直接通知) - 在系统操作的时候,遇到的各种bean通知事件进行通知。可以看到的是applicationEventMulticaster是一个标准的观察者模式,对于它内部的监听者applicationListeners,每次事件到来都会一一获取通知。
onRefresh()
留给子类来初始化它的Bean 给子容器(子类),子类重写这个方法,在容器刷新的时候可以自定义逻辑
这里不再写测试类。
registerListeners() 注册监听器
- 看源码(具体实现在
AbstractApplicationContext.class
)
/**
* Add beans that implement ApplicationListener as listeners.
* Doesn't affect other listeners, which can be added without being beans.
*/
protected void registerListeners() {
// 首先注册指定的静态事件监听器,在spring boot中有应用
// 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!
// 其次 注册普通的事件监听器
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// 如果有早期事件的话,在这里进行事件广播
/* 因为SimpleApplicationEventMulticaster尚未注册,无法发布事件,
* 因此早期的事件会保存在 earlyApplication 集合中,这里把它们取出来进行发布
* 所以早期事件的发布时间节点早于其他事件的
*/
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
/* 早期的事件广播器是一个 Set<ApplicationEvent> 集合,保存了无法发布的早期事件,当SimpleApplicationEventMulticaster创建完之后
* 随即进行发布,同时也要将其保存的事件进行释放
*/
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
我们来看一下Spring的事件监昕的简单用法
自定义监听事件以及监听器
/**
* 定义监听事件
* @author paidaxing
*/
public class TestEvent extends ApplicationEvent {
public String msg;
public TestEvent(Object source) {
super(source);
}
public TestEvent(Object source, String msg) {
super(source);
this.msg = msg;
}
public void print () {
System.out.println(msg) ;
}
}
/**
* 定义监听器
* @author paidaxing
*/
public class TestListeners implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof TestEvent){
TestEvent testEvent = (TestEvent) event;
testEvent.print();
}
}
}
添加配置文件
<bean id="testApplicationListener" class="com.vipbbo.spring.event.TestListeners"></bean>
测试类
@Test
public void TestListener(){
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationListeners.xml");
TestEvent testEvent = new TestEvent("hello", "msg1");
applicationContext.publishEvent(testEvent);
}
接下来我们开一下 测试类中applicationContext.publishEvent(testEvent);
这个方法的具体实现:
- 看源码(具体实现是在
AbstractApplicationContext.class
)
/**
* Publish the given event to all listeners.
* @param event the event to publish (may be an {@link ApplicationEvent}
* or a payload object to be turned into a {@link PayloadApplicationEvent})
* @param eventType the resolved event type, if known
* @since 4.2
*/
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
/*
* 支持两种事件:
* 1.直接继承ApplicationEvent
* 2.其他事件,会被包装为PayloadApplicationEvent,可以使用getPayload获取真实的通知内容
*/
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// 如果有预执行会添加到预执行,预执行在执行一次后会被置为null,以后都是直接执行
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
// 广播Event事件 这里需要看一下 multicastEvent() 方法的实现 具体在 SimpleApplicationEventMulticaster 类中
/* =============== 关于multicastEvent()方法 ===============
* 查找所有的监听者,依次遍历,如果有线程池,利用线程池进行发送,如果没有则直接发送;
* 如果针对比较大的并发量,我们应该采用线程池模式,将发送通知和真正的业务逻辑进行分离
* 在这个方法里面调用了 invokeListener(listener, event) 需要注意该方法里面的
* doInvokeListener(listener, event) 这个方法,这个方法里面调用了 listener.onApplicationEvent(event);
*
* */
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// 父bean同样广播
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
我们看到在该实现中有一个multicastEvent
方法,相关说明我在代码中有注释,我们来几句看一下multicastEvent这个方法的实现:
- 看源码(具体实现是在
SimpleApplicationEventMulticaster.class
)
SimpleApplicationEventMulticaster.class就是Spring默认的广播器
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
在这里我们看到了invokeListener(listener, event);
方法,继续往下追
- 看源码(具体实现在
SimpleApplicationEventMulticaster.class
)
/**
* Invoke the given listener with the given event.
* @param listener the ApplicationListener to invoke
* @param event the current event to propagate
* @since 4.1
*/
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
然后我们查看一下doInvokeListener(listener, event);
函数里面的具体实现,
- 看源码(具体实现在`SimpleApplicationEventMulticaster.class)
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass()) ||
(event instanceof PayloadApplicationEvent &&
matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception.
Log loggerToUse = this.lazyLogger;
if (loggerToUse == null) {
loggerToUse = LogFactory.getLog(getClass());
this.lazyLogger = loggerToUse;
}
if (loggerToUse.isTraceEnabled()) {
loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
finishBeanFactoryInitialization 初始化剩下的单实例(非惰性的)
- 看源码(具体实现在
AbstractApplicationContext.class
)
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 判断有无Conversion service(bean属性类型转换服务接口),并初始化
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));
}
// 如果beanFactory中不包含 EmbeddedValueResolver,则向其中添加一个 EmbeddedValueResolver
// EmbeddedValueResolver ->解析bean中的占位符和表达式
// 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));
}
// 初始化 LoadTimeWeaverAware 类型的bean
// LoadTimeWareAware --> 加载spring bean 时植入的第三方模块 如AspectJ
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
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);
// 冻结缓存的 BeanDefinition 元数据
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// 初始化其他非延迟加载的单例 bean **这是重点** 可以进去查看一下
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
- 源码分析
我们重点查看beanFactory.preInstantiateSingletons();
- 看源码(具体实现在
DefaultListableBeanFactory
.class)
不知到大家是否还记得 DefaultListableBeanFactory.class, 它是容器的基础
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
主要注意getBean(beanName);
函数
finishRefresh() 最后一步完成刷新过程
完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知
- 看源码(具体实现在
.class
)
/**
* Finish the refresh of this context, invoking the LifecycleProcessor's
* onRefresh() method and publishing the
* {@link org.springframework.context.event.ContextRefreshedEvent}.
*/
@SuppressWarnings("deprecation")
protected void finishRefresh() {
// 清空资源缓存
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// 初始化生命周期处理器
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// 调用生命周期的处理器的onRefresh()方法
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// 推送容器发送事件
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
if (!NativeDetector.inNativeImage()) {
LiveBeansView.registerApplicationContext(this);
}
}
Spring源码解析就告一段落了。想要获取更多精彩内容请:
微信搜索【码上遇见你】
或扫描下方二维码获取学习资料。
Spring源码阅读一的更多相关文章
- Bean实例化(Spring源码阅读)-我们到底能走多远系列(33)
我们到底能走多远系列(33) 扯淡: 各位: 命运就算颠沛流离 命运就算曲折离奇 命运就算恐吓着你做人没趣味 别流泪 心酸 更不应舍弃 ... 主题: Spring源码阅读还在继 ...
- 初始化IoC容器(Spring源码阅读)
初始化IoC容器(Spring源码阅读) 我们到底能走多远系列(31) 扯淡: 有个问题一直想问:各位你们的工资剩下来会怎么处理?已婚的,我知道工资永远都是不够的.未婚的你们,你们是怎么分配工资的? ...
- Spring源码阅读-ApplicationContext体系结构分析
目录 继承层次图概览 ConfigurableApplicationContext分析 AbstractApplicationContext GenericApplicationContext Gen ...
- Sping学习笔记(一)----Spring源码阅读环境的搭建
idea搭建spring源码阅读环境 安装gradle Github下载Spring源码 新建学习spring源码的项目 idea搭建spring源码阅读环境 安装gradle 在官网中下载gradl ...
- Spring源码阅读笔记02:IOC基本概念
上篇文章中我们介绍了准备Spring源码阅读环境的两种姿势,接下来,我们就要开始探寻这个著名框架背后的原理.Spring提供的最基本最底层的功能是bean容器,这其实是对IoC思想的应用,在学习Spr ...
- Spring源码阅读 之 配置的读取,解析
在上文中我们已经知道了Spring如何从我们给定的位置加载到配置文件,并将文件包装成一个Resource对象.这篇文章我们将要探讨的就是,如何从这个Resouce对象中加载到我们的容器?加载到容器后又 ...
- 搭建 Spring 源码阅读环境
前言 有一个Spring源码阅读环境是学习Spring的基础.笔者借鉴了网上很多搭建环境的方法,也尝试了很多,接下来总结两种个人认为比较简便实用的方法.读者可根据自己的需要自行选择. 方法一:搭建基础 ...
- Spring源码阅读系列总结
最近一段时间,粗略的查看了一下Spring源码,对Spring的两大核心和Spring的组件有了更深入的了解.同时在学习Spring源码时,得了解一些设计模式,不然阅读源码还是有一定难度的,所以一些重 ...
- Spring源码阅读笔记
前言 作为一个Java开发者,工作了几年后,越发觉力有点不从心了,技术的世界实在是太过于辽阔了,接触的东西越多,越感到前所未有的恐慌. 每天捣鼓这个捣鼓那个,结果回过头来,才发现这个也不通,那个也不精 ...
- idea构建spring源码阅读环境
注:由于文章不是一次性完成,下文中的test1目录和test目录应为同一个目录. (一)安装git和Gradle Spring项目托管在github之上,基于Gradle来构建项目.所以要想搭建Spr ...
随机推荐
- DQL,DML,DDL,DCL分别是什么?
SQL语言共分为四大类:数据查询语言DQL,数据操纵语言DML,数据定义语言DDL,数据控制语言DCL. 数据查询语言DQL数据查询语言DQL基本结构是由SELECT子句,FROM子句,WHERE子句 ...
- springboot全局异常封装案例
@ControllerAdvice三个场景:>https://www.cnblogs.com/lenve/p/10748453.html 全局异常处理 全局数据绑定 全局数据预处理 首先定义一个 ...
- ES6——类表达式
//类表达式 const Person1 = class{ constructor(){ console.log('aa') } } //也可以跟上类名P,但是变量P在class外部是访问不到的,在c ...
- 怎样去除EXCEL中的重复行
工具/原料 安装了EXCEL2010的电脑一台 步骤/方法 假如我们的表格中有下图所示的一系列数据,可以看出其中有一些重复. 首先我们选中所有数据.可以先用鼠标点击"A1单元格&qu ...
- Java并发之AQS原理解读(二)
上一篇: Java并发之AQS原理解读(一) 前言 本文从源码角度分析AQS独占锁工作原理,并介绍ReentranLock如何应用. 独占锁工作原理 独占锁即每次只有一个线程可以获得同一个锁资源. 获 ...
- css 边框添加三角形指向,简单粗暴,易学易懂
构建一个 div , class 随便命名 css 部分 class 名字 { position: relative; // 相对定位是重点 } class名字:before,class名字:afte ...
- vue 引用省市区三级联动(element-ui Cascader)
npm 下载 npm install element-china-area-data -S main.js import {provinceAndCityData,regionData,provinc ...
- Vue Router路由导航及传参方式
路由导航及传参方式 一.两种导航方式 ①:声明式导航 <router-link :to="..."> ②:编程式导航 router.push(...) 二.编程式导航参 ...
- 代码保留格式(高亮)复制到Word(转载)
将代码保持高亮复制粘贴到word上,一些方法如下: 方法一:借助网站http://www.planetb.ca/syntax-highlight-word/(代码有编号,整体排版精美令人舒适,但语言有 ...
- 模拟9:T1:斐波那契
Description: 题目描述: 小 C 养了一些很可爱的兔子. 有一天,小 C 突然发现兔子们都是严格按照伟大的数学家斐波那契提出的模型来进行繁衍:一对兔子从出生后第二个月起,每个月刚开 ...