spring源码分析之ApplicationContext
本篇博文主要针对ApplictionContext的功能进行详细的解释说明,主要的实例是以ClassPathApplicationContext为主进行介绍了,核心分析了ApplicationContext在启动过程中做的一些操作,比如容器刷新准备,调用BeanFactory后置处理器,注册bean后置处理器,国际化,事件监听,容器创建结束的lifycecly的启动等,需要通过这篇文章能帮助大家很
目录
二、ClassPathXmlApplicationContext类
2.1、obtainFreshBeanFactory()方法分析
3.3、注册ApplicationContextAwareProcessor
4.1、什么是BeanFactoryPostProcessors实例
4.2、invokeBeanFactoryPostProcessors方法
10、刷新完成后操作
前言:通过一篇博文Spring源码分析之一BeanFactory相关,我们大致了解了BeanFactory体系架构相关的知识点,但是其中的XmlBeanFactory已经被声明为过时了,下面我们需要请出一个常用的针对BeanFactory扩展接口ApplicationContext,在接下来的本篇博文中(可能会分多篇博文讲解)主要介绍了ApplicationContext相关的功能点,ApplicationContext提供了更多的扩展功能。下面我们来一点一点揭开其神秘的面纱。
一、初识ApplicationContext
1、示例
之前在刚开始接触spring源码的容器类我们主要分析了XmlBeanFactory(现在我们发现该类已经被spring官方声明为过时了)
我们在现实场景中最常用的其实是ApplicationContext的体系实现类,该接口和BeanFactory一样都是Spring用来管理bean实例的
容器对象,但是ApplicationContext提供的功能更丰富和实用。话不多少下面让我们来一起了解一下ApplicationContext实例ClassPathXmlApplicationContext。
@Test
public void start(){
ApplicationContext context = new ClassPathXmlApplicationContext(
new String[]{"spring/spring-dao.xml","spring/spring-service.xml","spring/spring-web.xml"});
DataSource dataSource1 = context.getBean("dataSource", DataSource.class);
System.out.println(dataSource1.toString());
}
2、UML类图
从ClassPathXmlApplicationContext类相关的UML类图中可以知道ApplicationContext在继承BeanFactory的基础上也有相关的扩展。所以ApplicationContext提供了比BeanFactory更多更强大的功能。
下面我们依据new ClassPathXmlApplicationContext() 来分析该实例的一些功能点
二、ClassPathXmlApplicationContext类
1、构造方法
相比于XmlBeanFactory ApplicationContext的ClassPathXmlApplicationContext,支持加载多个资源文件。
/**
* ClassPathXmlApplicationContext的构造函数
* @param configLocations 配置资源数组
* @param refresh 是否刷新容器标识(该标识对应的刷新接口是该实例的核心方法)
* @param parent 父类的对象
* @throws BeansException
*/
public ClassPathXmlApplicationContext(String[] configLocations,
boolean refresh, ApplicationContext parent) throws BeansException {
//设置其父类实例
super(parent);
//添加并解析资源名称 (数组) //针对特殊属性的的资源名比如${var} 会进行相关的变量解析。
this.setConfigLocations(configLocations);
if (refresh) {
//刷新容器接口
this.refresh();
}
}
上述ClassPathXmlApplicationContext实例化的过程中,除了调用父类构造方法,设置支援属性信息之外,最核心的方法就是refresh()方法,下面我们来分析一下refresh()方法做了一些什么。
2、refresh()方法
//下面我们来看一下ApplicationContext的核心方法resresh();
//该方法几乎包含了ApplicationContext的所有功能,所以该方法比较复杂
//目前先大致简要叙述各个方法的作用,后面我们一一分析
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//刷新容器之前的准备操作
//相关变量初始化,以及对系统属性验证
prepareRefresh();
// 创建新的BeanFactory 这个对象实例也是该类为啥拥有和beanFactory一样功能的原因
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//beanFactory实例对象的一些特殊规则设置,添加一些实例bean,bean后置处理器,忽略某些依赖注入、指定某些依赖注入等
prepareBeanFactory(beanFactory);
try {
//spring的钩子函数,为子类扩展提供的方法,子类可以继承该类并重写该方法
//看到其他子类实现大多是添加一些BeanPostProcessor实例
postProcessBeanFactory(beanFactory);
//调用BeanFactoryPostProcessor 的相关方法主要是
//BeanDefinitionRegistryPostProcessor实例对象的postProcessBeanDefinitionRegistry()方法
//或者BeanFactoryPostProcessor 的postProcessBeanFactory()方法
invokeBeanFactoryPostProcessors(beanFactory);
//注册BeanPostProcessor(该方法只是注册,真正的调用是在bean的实例化阶段进行的)
registerBeanPostProcessors(beanFactory);
//初始化国际资源 我们可以针对不同语言或者地区提供不同的资源信息
//只需要设置相关的语言地区 就可以获取对应语言或者地区的资源信息 此处不关注
initMessageSource();
//初始化事件广播实例对象 该对象主要管理spring所有的ApplicationListener实现类
//使用观察者模式 如果context 发布了一些相关的事件 则该广播对象会通知所有的事件监听器
//最终调用相关的事件监听器 处理对应的事件
initApplicationEventMulticaster();
//子类进行扩展的钩子方法
onRefresh();
//注册事件监听器 上面实例化了事件广播实例
registerListeners();
//单例对象的初始化
finishBeanFactoryInitialization(beanFactory);
//容器实例化后通知所有的Lifecycle接口的start()方法
finishRefresh();
}
catch (BeansException ex) {
logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);
//实例化异常 销毁相关的bean
destroyBeans();
//重置刷新标识
cancelRefresh(ex);
throw ex;
}
}
}
从上面的代码中可以看到refresh()几乎包含了该类实例化的所有核心方法比较复杂,该方法主要逻辑罗列如下:
- prepareRefresh(): 刷新容器之前的准备操作,相关变量初始化,以及对系统属性验证。
- obtainFreshBeanFactory():创建新的BeanFactory
- prepareBeanFactory(beanFactory): beanFactory实例对象的一些特殊规则设置
- postProcessBeanFactory()方法:spring的钩子函数,为子类扩展提供的方法
- invokeBeanFactoryPostProcessors()方法:调用BeanFactoryPostProcessor的相关方法。
- registerBeanPostProcessors()方法:注册BeanPostProcessor
- initMessageSource()方法:初始化国际资源
- initApplicationEventMulticaster()方法:初始化事件广播实例对象 该对象主要管理spring所有的ApplicationListener实现类,使用观察者模式 如果context 发布了一些相关的事件 则该广播对象会通知所有的事件监听器
- onRefresh()方法: 子类进行扩展的钩子方法。
- finishBeanFactoryInitialization()方法:单例对象的初始化。
- finishRefresh()方法:容器实例化后通知所有的Lifecycle接口的start()方法。
- destroyBeans()、cancelRefresh()实例化异常的相关操作。
三、refresh()方法的详细分析
1、prepareRefresh()
容器实例化时候执行刷新之前的准备操作。
1.1、源码分析
//1、容器刷新之前的准备操作
protected void prepareRefresh() {
//获取容器启动时间,和后面容器启动完成后的时间只差 作为容器启动时间的统计
this.startupDate = System.currentTimeMillis();
//设置容器状态为激活
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
//该方法是留给子类去进行扩展的
initPropertySources();
//对于容器需要依赖某些系统变量才能正常工作的场景
//此处对于环境中的必填参数进行相关校验
getEnvironment().validateRequiredProperties();
}
该方法主要是在ApplicationContext启动之前设置一些启动参数,比如激活状态active,容器启动时间startupDate ,以及子类扩展填充属性信息initPropertySources(),以及系统必填参数校验validateRequiredProperties()。针对该方法我们使用一个示例来理解一下其子类设置相关属性配置,并设置自动校验。
1.2、prepareRefresh()示范
自定义ApplicationContext类
//该方法设置了两个参数 一个开始时间 一个容器激活状态
//紧接着提供了一个供子类扩展的方法initPropertySources() 使用者可以通过重写该类 进行一些业务相关变量的初始化操作
//同时提供了一个对必填字段的校验方法getEnvironment().validateRequiredProperties();
//该方法的校验是Environment对象委托其属性AbstractPropertyResolver 调用其validateRequiredProperties()方法实现
//该方法有什么作用呢?
//下面我们针对如下业务场景:对于容器启动需要设置相关系统属性classPath,且对系统属性进行校验,
// 则此处继承ClassPathXmlApplicationContext重写了initPropertySources()方法
//重写的方法中 主要为ApplicationContext设置系统变量,并添加必填字段的校验
class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext{
MyClassPathXmlApplicationContext(String... configLocations){
super(configLocations);
}
@Override
protected void initPropertySources() {
//子类扩展该方法进行了一些系统变量添加
String classPath = "/usr/local/jdk1.9/bin";
Map<String,Object> paramMap = new HashMap<String, Object>();
paramMap.put("classPath",classPath);
SystemEnvironmentPropertySource seps = new SystemEnvironmentPropertySource("env", paramMap);
//设置必填属性
getEnvironment().getPropertySources().addFirst(seps);
getEnvironment().setRequiredProperties("classPath");
//设置环境中的必填参数alis校验 但是初始化属性中没有该属性会报错
getEnvironment().setRequiredProperties("alis");
}
}
测试 如果注释掉最后一行代码 则实例化该ApplicationContext在必填参数校验会报错。
2、obtainFreshBeanFactory()
ApplicationContext之所以包含有BeanFactory实例的特征,就是因为在该方法中实例化了一个BeanFactory,更确切的说是一个DefalutListBeanFactory实例,从而使其拥有了BeanFactory的相关功能。
2.1、obtainFreshBeanFactory()方法分析
/**
* 2、加载xml形式配置的bean定义 初始化BeanFactory实例
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//见名知意 刷新BeanFactory
refreshBeanFactory();
//创建新的BeanFactory实例 DefaultListBeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
该方法中主要主要包含两个方法:
- refreshBeanFactory()主要是删除原先的beanFactory实例,并再创建新的BeanFactory实例。
- getBeanFactory() 从该容器中获取上一个方法创建的beanFactory实例。
两个方式均在AbstractRefreshableApplicationContext类中进行了相关实现。
2.2、refreshBeanFactory()
//具体是AbstractRefreshableApplicationContext的refreshBeanFactory()实现
protected final void refreshBeanFactory() throws BeansException {
destroyBeans() 调用beanFactory容器中所有单例对象的销毁方法(实现了DisposableBean接口的bean
// 或者在xml的<bean id="xx" class="XXX" destroy-method="destroyBeanTest"/> 声明的 销毁方法)
//接着销毁beanFactory容器实例
//为什么要先销毁存在的 重新创建一个新的beanFactory
//笔者认为原因大概是因为 大部分情况下刷新接口调用频率很小,而且大多涉及到了spring容器中的单例bean实例的增、删、改
//而spring 管理的bean很多的情况下 没有提供相关的api对于相关bean实例的处理,在spring整个环境比较复杂的情况下
//直接销毁在重新创建,比耗费大量的逻辑处理要好的多,虽然耗时但是并不频繁,不失为一个折中的好办法。
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//2、创建一个DefaultListBeanFactory实例对象
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
//3、beanFactory实例功能的填充
//3.1、该方法主要涉及两个参数的自定义
//(1)、allowBeanDefinitionOverriding 是否允许同名的Bean实例覆盖
// 在大型项目开发过程中,各个服务项目单独开发,集成在一起的时候可能出现上面的问题
//(2)、allowCircularReferences 是否允许循环依赖(循环依赖不多多说,感兴趣的读者可以看看笔者的博客,不贴链接了,
// 自己关注,自己看,看给你惯的) 两者默认都是true
//spring提供这种方法让我们可以改变这两个属性,从而改变整个beanFactory容器的特性(一般不需要改)
customizeBeanFactory(beanFactory);
//转载xml中定义的bean实例(和之前的我们解读beanFactory实例化一致)
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("");
}
}
该方法主要逻辑如下:
- 销毁BeanFactory实例,重新创建BeanFactory实例,
- customizeBeanFactory()方法设置BeanFactory实例的属性:
- 1、allowBeanDefinitionOverriding 是否允许同名的Bean实例覆盖。
- 2、allowCircularReferences 是否允许循环依赖。
- spring提供这种方法让我们可以改变这两个属性,从而改变整个beanFactory容器的特性
- 加载Xml配置和BeanFactory实例解析xml配置一致, 转换为BeanDefintion。
上面对于创建的BeanFactory实例后设置相关属性着重介绍一下
allowBeanDefinitionOverriding属性
该属性的含义是否允许同名bean实例覆盖,该场景主要发生在大型项目开发过程中,各个服务项目单独开发,集成在一起的时候可能同名Bean实例。这里属性默认为true,即允许同名bean覆盖。
//补充同名bean覆盖的问题示例
//spring-bean1.xml
<bean id="demoService" class="com.soecode.lyf.service.impl.DemoTwoServiceImpl"
destroy-method="destroyBeanTest"/>
//spring-bean2.xml
<bean id="demoService" name="service" class="com.soecode.lyf.service.impl.DemoServiceImpl" />
如上两个xml配置都声明同id的demoService(一定是不同xml声明同名bean,而不是在同一个xml声明两个同名的bean 会在解析xml的时候报另一个错误)。则会出现按照xml加载顺序后者覆盖前者的情况。
allowCircularReferences 属性
关于循环依赖,读者可参看笔者的这边博文 spring循环依赖。
3、prepareBeanFactory()方法
//perpareBeanFactory()方法 为beanFactory进行一些特殊的相关设置
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//设置类加载器
beanFactory.setBeanClassLoader(getClassLoader());
//设置SPEL表达式语言的支持
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//设置属性编辑注册器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
//先注册ApplicationContextAwareProcessor bean后置处理器 主要用于spring初始化
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.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
//增加spring对AspecJ的支持
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
//注册相关的环境env实例对象
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());
}
}
perpareBeanFactory()方法 为beanFactory进行一些特殊的相关设置,主要逻辑如下:
- 设置类加载器ClassLoader、表达式语言支持StandardBeanExpressionResolver、属性编辑注册器ResourceEditorRegistrar
- ApplicationContextAwareProcessor 添加创建实例的时候编码设置相关的XXXWare同时设置忽略自动装配:EnvironmentAware,EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware(忽略实现了如下接口的实现类中的setter方法的实例注册 比如服务ServiceA组件实现了EnvironmentAware 则其就会重写其中的SetEnvironment(Environment environment) 这里对其的注入忽略,注意此处 对spring有一定了解的同学其实知道对于实现了XXXAware接口的bean实例创建的时候会在其对应的initializeBean()调用我们注册的会调用ApplicationContextAwareProcessor后置处理器 postProcessBeforeInitialization()方法的 invokeAwareInterfaces()方法其对应的setXXX()注入 请和ignoreDependencyType用法区分开) 请参考有关ignoreDependencyInterface和ignoreDependencyType区别
- 注入指定的依赖 在Spring自动装配的时候如果一个接口有多个实现类,并且都已经放到IOC中去了那么自动装配的时候就会出异常,这里我们可以使用registerResolvableDependency() 指定注入特定的实例 。 在多个实例情况下指定注入特定实例
- 添加bean后置处理器 LoadTimeWeaverAwareProcessor 增加Aspectj的支持
- 注册默认的环境bean实例
3.1、添加SpringEL表达式的支持
设置StandardBeanExpressionResolver实例 用于springEl表达式解析支持 从而可以使我们使用El表达式的形式 * 引用spring容器中的一些实例信息。
SpEL使用#{}去进行使用,我们可以通过xml配置、注解的方式使用SpringEL表达式语法。
<!--xml配置形式使用el表达式-->
<!-- 测试SpEL的使用 -->
<bean id="bookOne" class="com.soecode.lyf.entity.Book">
<property name="name" value="平凡的世界" />
<property name="author" value="路遥" />
</bean>
<bean id="bookTwo" class="com.soecode.lyf.entity.Book">
<!-- 此处使用el表达式获取bookOne实例的属性 -->
<property name="name" value="#{bookOne.name}" />
<property name="author" value="#{bookOne.author}" />
</bean>
<bean id="reader" class="com.soecode.lyf.entity.Reader">
<!-- 此处使用el表达式获取bookOne实例的属性 -->
<property name="name" value="#{bookTwo}" /></bean>
//类似于
<bean id="reader" class="com.soecode.lyf.entity.Reader">
<!-- 此处使用el表达式获取bookOne实例的属性 -->
<property name="name" ref="bookTwo" />
</bean>
EL表达式详细用法参考:https://blog.csdn.net/ya_1249463314/article/details/68484422
//注解形式使用el表达式
@Component
public class MyMessage2 {
@Value("#{systemProperties['user.language']}")
private String message;
public String getMessage() {
return message;
}
}
//beanFactory中注入StandardBeanExpressionResolver 主要是在Spring初始化bean
//AbstractAutowireCapableBeanFactory类的 applyPropertyValues()方法
3.2、注册属性编辑器
- 何为属性编辑器
属性编辑器的作用是针对某些属性将其转换为特定属性对象的工具方法,我们可以通过自定义属性编辑器,也可以使用spring自定义的属性编辑器进行属性转换
- 该对象主要应用场景
1、MVC模式下 json数据中的date类型 是String 则请求到后台对应的Controller 会用对应的属性编辑器将其转换为Date类型
2、xml配置中的所有值的设置都是String,这个时候如果给bean的复杂类型属性设置值,需要用到属性编辑器
- 属性编辑器相关的类及接口
PropertyEditor; 属性编辑接口类
PropertyEditorSupport;
CustomDateEditor
PropertyEditorRegistrar;
PropertyEditorRegistry;
PropertyEditorRegistrySupport;
- 注册、调用方式
在该方法中beanFactory设置一个 ResourceEditorRegistrar 其registerCustomEditors()方法中注册了一些常见的属性编辑器
该类的registerCustomEditors()方法是什么时候调用的呢? 通过追踪调用链发现一个我们比较熟悉的方法
AbstractBeanFactory 的initBeanWrapper()方法中该方法被调用了
我们顺便来回忆一下initBeanWrapper()的使用场景: spring在初始化bean实例的时候 构造器实例化BeanWrapper
后会调用initBeanWrapper(bw)方法 在该方法中调用了registerCustomEditors() 从而支持Bean的属性转换。
//代码调用地方
(AbstractAutowireCapableBeanFactory类的doCreateBean()方法 createBeanInstance()方法)
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);、
3.3、注册ApplicationContextAwareProcessor
该类是一个bean后置处理器 会在bean实例化的时候用其postProcessBeforeInitialization().
这里我们需要关注的是invokeAwareInterfaces()方法。代码很简单主要就是针对bean实例实现XXXAware的接口 手动注入相关的组件,ignoreDependencyInterface同时忽略相关的XXXAware接口的依赖注入,registerResolvableDependency显示声明 遇到如下接口实例注入指定的依赖实例 这里针对相同接口多实例如何注入的问题进行处理 使用spring显示指定的依赖注入。
3.4添加对AspectJ的支持
检查容器中是否包含名称为loadTimeWeaver的bean,实际上是增加Aspectj的支持。
AspectJ采用编译期织入(也叫静态代理、编译时增强)、类加载期织入(也叫动态代理、运行时增强、)两种方式进行切面的织入。
添加BEAN后置处理器:LoadTimeWeaverAwareProcessor,在BEAN初始化之前检查BEAN是否实现了LoadTimeWeaverAware接口,如果是,则进行加载时织入,即静态代理。
3.5 添加环境相关的bean实例
注入了三种类型的env实例
- environment: 系统环境实例对象 包含下面的两种类型的环境变量 jdk等应用服务相关的变量,操作系统相关的变量
- systemProperties: jdk等应用服务相关的变量
- systemEnvironment: 操作系统相关的变量
4、BeanFactoryPostProcessors
4.1、什么是BeanFactoryPostProcessors实例
spring容器初始化时,从资源中读取到bean的相关定义后,保存在beanFactory的成员变量中(参考DefaultListableBeanFactory类的成员变量beanDefinitionMap),在实例化bean的操作就是依据这些bean的定义来进行实例化,而在实例化之前,spring允许我们通过自定义扩展来改变bean的定义,定义一旦变了,后面的实例也就变了,而beanFactory后置处理器,即BeanFactoryPostProcessor就是用来改变bean定义的;我们应用最常见的BeanFactoryPostProcessor 实现类是PropertyPlaceholderConfigurer该类支持我们使用${xxx}来声明bean定义的,该bean实例化的时候 先生成对应的BeanDefintion 我们的PropertyPlaceholderConfigurer 会获取配置中的相关信息最终修改BeanDefinition。
/**
* 比如
* //该方式便是声明了一个PropertyPlaceholderConfigurer实例
* <context:property-placeholder location="classpath:jdbc.properties" />
*
* <!-- 2.数据库连接池 bean定义中的属性使用${变量引用} -->
* <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
* <!-- 配置连接池属性 -->
* <property name="driverClass" value="${jdbc.driver}" />
* <property name="jdbcUrl" value="${jdbc.url}" />
* <property name="user" value="${jdbc.username}" />
* <property name="password" value="${jdbc.password}" />
* </bean>
*/
在实例化ComboPooledDataSource实例的时候,会通过PropertyPlaceholderConfigurer修改该DataSource对应的BeanDefintion将其中的属性占位符通过读取的配置信息替换(改变了DataSource对应的BeanDefintion的定义信息 )
BeanPostProcessor和BeanFactoryPostProcessor两者的区别
他们是Spring提供的对bean的功能进行扩展的接口,
作用于范围:
* 前者针对某些bean实例进行功能的扩展,针对某个具体的bean进行处理,是bean级别的处理。
* 后者是针对整个Bean的工厂进行处理,是BeanFactory级别的处理。
使用方式:
* 前者(前者实例化的时候不会立即执行器对应的方法)在bean实例化的时候,从容器总获取对符合条件的处理器实例
* 应用其postProcessBeforeInitialization()和postProcessAfterInitialization()
* 后者是spring容器加载任何实现给接口的实例的时候,会在spring容器载入所有的bean的配置之后执行postProcessBeanFactory()方法
4.2、invokeBeanFactoryPostProcessors方法
/**
* 4、执行对应的beanFactoryPostProcessors 后置处理器
* invokeBeanFactoryPostProcessors()方法委托给PostProcessorRegistrationDelegate 调用其
* invokeBeanFactoryPostProcessors()方法
*/
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//保存常规的BeanFactoryPostProcessors集合
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//保存是BeanDefinitionRegistryPostProcessor实例的集合
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
//遍历所有的BeanFactoryPostProcessor是BeanDefinitionRegistryPostProcessor
//执行其postProcessBeanDefinitionRegistry()
// 该方法主要是针对@Configuration注解修饰的bean进行相关的解析
// 并添加该后置处理器到registryProcessors集合,非BeanDefinitionRegistryPostProcessor 添加到regularPostProcessors集合中
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
//获取到BeanDefinitionRegistryPostProcessor 实例且实现了PriorityOrdered接口的后置处理器集合
// 排序调用其postProcessBeanDefinitionRegistry()方法 并存放到registryProcessors
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 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.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
//获取到BeanDefinitionRegistryPostProcessor 实例且实现了Order接口的后置处理器集合
//排序调用其postProcessBeanDefinitionRegistry()方法 并存放到registryProcessors
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.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
//获取其他没有排序的BeanDefinitionRegistryPostProcessor 实例
//排序调用其postProcessBeanDefinitionRegistry()方法 并存放到registryProcessors
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.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
//执行registryProcessors或者regularPostProcessors集合其BeanPostProcessor的postProcessBeanFactory()方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
//如果不是BeanFactory不是BeanDefinitionRegistry 则直接调用其BeanPostProcessor的postProcessBeanFactory()方法
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
//获取 BeanFactoryPostProcessor实例的集合列表 逻辑和上面获取BeanDefinitionRegistryPostProcessor实例逻辑一样
//也是实现PriorityOrdered接口,Order接口和其他非排序接口的 BeanFactoryPostProcessor
//调用集合中的其BeanPostProcessor的postProcessBeanFactory()方法
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)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
beanFactory.clearMetadataCache();
}
上面的代码很对但是逻辑实现很简单,先获取spring内部的已经存在的BeanFactoryPostProcesser 这里需要针对其扩展子类BeanDefinitionRegistryPostProcessor进行处理 先执行其所有的BeanDefinitionRegistryPostProcessor实例的postProcessBeanDefinitionRegistry()方法,接着执行所有内部BeanFactoryPostProcesser (包含BeanDefinitionRegistryPostProcessor)的postProcessBeanFactory()方法。
接着获取用户自定义的BeanFactoryPostProcesser,获取的BeanFactoryPostProcesser又分成两种类型一种BeanDefinitionRegistryPostProcessor(继承BeanFactoryPostProcessor)实例对象,另一种是普通的BeanFactoryPostProcessor实例对象,该两者主要是前者需要先调用其postProcessBeanDefinitionRegistry() 后面会和通的BeanFactoryPostProcessor实例一样调用其postProcessBeanFactory()。
两者都需要按顺序调用其实现PriorityOrdered,Order,其他BeanFactoryPostProcesser的方法。
5、注册BeanPostProcessor
/**
* 5、注册所有的BeanPostProcessor 所有的beanPostProcessor
* 会被保存在BeanFactory的beanPostProcessors的列表中 在spring中进行相关bean实例化的时候调用
* 常见bean后置处理器有InstantiationAwareBeanPostProcessor和DestructionAwareBeanPostProcessor等
* 后面我们会再了解
* @param beanFactory
* @param applicationContext
*/
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
//从beanDefinition列表中获取所有BeanPostProcessor实例的所有后置处理器名列表
//主要获取到我们自定义的后置处理器
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
//添加一个BeanPostProcessorChecker 后置处理器
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
//spring中主要分为四种类型的bean后置处理器
//1、实现了PriorityOrdered接口的 有序和有优先级BeanPostProcessor
//2、MergedBeanDefinitionPostProcessor实例类型的BeanPostProcessor
//3、实现了Order接口的BeanPostProcessor
//4、其他无序的BeanPostProcessor
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
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);
}
}
//下面分别对上面的四种BeanPostProcessor 进行注册
//注册实现了PriorityOrdered接口的 有序和有优先级BeanPostProcessor
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
//注册实现了Order接口的BeanPostProcessor
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
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<>();
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
//因为internalPostProcessors和priorityOrderedPostProcessors两个列表有重复元素
//但是此处注册不会重复注册 因为注册的逻辑
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// 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));
}
7、注册事件监听广播类
/**
* 6、初始化事件广播类 该类会将所有发布的事件通知给其管理的所有事件监听器 从而让spring能对关注的事件进行及时的处理
*/
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//如果容器中已经存在事件广播对象实例(applicationEventMulticaster)则直接获取
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 + "]");
}
}
else {
//如果容器中没有事件广播对象实例(applicationEventMulticaster)则创建一个默认的SimpleApplicationEventMulticaster实例并注册
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
//下面我们关注一下默认的SimpleApplicationEventMulticaster实例
//事件广播实例主要操作是管理和维护所有的ApplicationListener实例和对对应事件进行广播
//我们主要关注其事件广播相关的方法multicastEvent()方法
/**
* 从该方法中我们清楚的了解到,一旦遇到事件发布 该对象将时间通知给其管理的所有ApplicationListener
* 继续追踪invokeListener() 最终调用 listener.onApplicationEvent(event) 和我们的示范例子对应上了
* @param event
* @param eventType
*/
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);
}
}
}
7、注册监听器实例
/**
* 7、注册事件监听实例
*/
protected void registerListeners() {
//对硬编码形式注册的监听器处理 交给广播实例对象管理(广播实例对象在其前已经实例化完成)
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 对于配置文件注册的监听器进行处理 先根据监听器名称实例化监听器对象 再交由广播实例对象管理
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
//广播实例对象和所有的事件监听器已经准备就绪 发布应用在没有广播之前的早期一些事件
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
8、主要进行一些单例对象的加载
/**
* 8、主要进行一些单例对象的加载
* 主要分成两种类型特殊的beanDefinition 和普通的单例对象
* 特殊的beanDefintion ConversionService实例、LoadTimeWeaverAware实例
* 其他普通的单例对象
* @param beanFactory
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 初始化ConversionService实例
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));
}
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
//实例化LoadTimeWeaverAware对象
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);
//冻结配置 此时注册在spring容器中的bean定义不会被修改
beanFactory.freezeConfiguration();
//这里主要调用工厂的getBean()方法实例化单例对象
beanFactory.preInstantiateSingletons();
}
9、刷新完成后操作
/**
* 9、 ApplicationContext实例化完成的刷新操作
*/
protected void finishRefresh() {
//清除context级别的资源文件的缓存
clearResourceCaches();
//初始化LifecycleProcessor 管理所有实现Lifecycle接口实例的启动和销毁
initLifecycleProcessor();
//调用上面初始化的LifecycleProcessor实例的onRefresh
//执行所有Lifecycle接口的sart()方法
getLifecycleProcessor().onRefresh();
//发布容器刷新事件
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
在Spring中提供了Lifecycle接口 该接口中包含start()和stop()方法。实现此接口后spring会保证在启动的时候调用其start()方法,并在销毁的时候调用其stop()方法上面就给了相关实现通过实例化tLifecycleProcessor该实例启动则调用其onRefresh()方法 则会调用所有实现Lifecycle接口的start()方法关注则调用其onClose()方法 则会调用所有实现Lifecycle接口的stop()方法。
更多推荐
所有评论(0)