容器与上下文
BeanFactory家族是用来做容器创建和初始化的类,同时spring还提供了ApplicationContext接口用于扩展BeanFactory中的现有功能。一般在绝大多数场景,ApplicationContext就是首选的。
ApplicationContext是Spring框架中重要的容器之一,它是BeanFactory的超集,提供了更多的企业级特性和功能。ApplicationContext具有以下优势:
更快的启动速度。
监听和响应Bean生命周期事件。
支持模块化编程(例如通过不同的XML文件或Java类定义不同的bean)。
内置支持AOP、数据校验和事件发现等框架。
提供覆盖框架默认设置的能力。
允许开发者通过参数化配置很容易地管理多个环境下的部署。
背后的原理是ApplicationContext在启动时实例化Bean并注入它们,同时负责管理对象的整个生命周期。当需要获取一个Bean时,ApplicationContext会检查是否已经存在该Bean实例,如果不存在,则创建新实例并返回该实例给调用方。ApplicationContext还支持在构造函数参数或方法参数中注入Bean、解析属性占位符和SpEL表达式等高级设置。
ApplicationContext应用场景非常广泛。
例如,在使用Spring MVC框架开发Web应用程序时,我们可以使用XmlWebApplicationContext或AnnotationConfigWebApplicationContext来加载Spring配置文件。参考以下链接:
还可以使用ClassPathXmlApplicationContext加载类路径下的XML文件。另外,在需要动态注册组件的情况下,我们可以使用GenericApplicationContext来自定义Bean
使用ApplicationContext加载XML生成bean的流程如下:
// 使用BeanFactory
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("spring-beans.xml"));
MyTestBean bean = (MyTestBean) bf.getBean("myTestBean");
// 使用ApplicationContext
ApplicationContext bf = new ClassPathXmlApplicationContext("beanFactoryTest.xml");
从这段代码中可以看出,二者提供的用法是基本一致的
上下文的加载流程
ClassPathXmlApplicationContext
核心成员变量
// xml配置文件的路径,继承自AbstractRefreshableConfigApplicationContext
private String[] configLocations;
// 继承自AbstractApplicationContext,是一个监控refresh方法和destory方法的同步锁
private final Object startupShutdownMonitor = new Object();
// 继承自AbstractApplicationContext,是BeanFactoryPostProcessors合集
private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>()
构造函数
// 使用ApplicationContext
ApplicationContext bf = new ClassPathXmlApplicationContext("beanFactoryTest.xml");
从这行源码入手,找到了下面这个构造函数:
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
这里做了三件事:
super执行了其父类的构造函数
setConfigLocations用于设置配置路径
refresh用于对数组进行解析和加载
一直追溯到父类构造函数
public AbstractApplicationContext(@Nullable ApplicationContext parent) {
this();
setParent(parent);
}
在这个场景下,parent = null
,忽略,继续看
public AbstractApplicationContext() {
this.resourcePatternResolver = getResourcePatternResolver();
}
是在给资源解析器赋值,跟进getResourcePatternResolver方法
protected ResourcePatternResolver getResourcePatternResolver() {
return new PathMatchingResourcePatternResolver(this);
}
原来是PathMatchingResourcePatternResolver,是老朋友了
setConfigLocation
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++) {
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
……
}
核心是这部分,运行传多个配置文件路径,会以数组形式存储到configLocations属性,然后遍历每一个路径,调用resolvePath方法解析给定的路径数组,当然,如果数组中包含特殊符号,如${var},那么在resolvePath中会搜寻匹配的系统变量并替换。
refresh - 上下文刷新核心方法
继承自AbstractApplicationContext,是所有上下文执行refresh时候的统一模板方法,定义了整个 Spring 上下文加载的流程。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
……
}
}
首先可以看到,整个refresh方法都是在同步锁startupShutdownMonitor的监控下完成的。其中的方法可知是原子性的。其中的步骤包括:
准备环境
prepareRefresh();
prepare工作,对系统属性或者环境变量进行准备和验重,见prepareRefresh方法
xml文件读取
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
初始化BeanFactory,并进⾏XML⽂件读取,见obtainFreshBeanFactory方法
填充BeanFactory功能
prepareBeanFactory(beanFactory);
对BeanFactory进行各种功能填充,见prepareBeanFactory方法
处理子类覆盖方法
postProcessBeanFactory(beanFactory);
处理子类的覆盖方法,见postProcessBeanFactory方法
注册各类BeanFactory处理器
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
invokeBeanFactoryPostProcessors(beanFactory);
激活各种beanFactory处理器,见invokeBeanFactoryPostProcessors方法
注册Bean创建过程中的可插入式处理器
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
注册拦截Bean创建的Bean处理器,这⾥只是注册,真正的调⽤是在getBean时候,见registerBeanPostProcessors方法
初始化Message源
initMessageSource();
为上下⽂初始化Message源,即不同语⾔的消息体 ,国际化处理,见initMessageSource方法
初始化应用消息广播器
initApplicationEventMulticaster();
初始化应⽤消息⼴播器,并放⼊“applicationEventMulticaster”bean中,见initApplicationEventMulticaster方法
refresh扩展点
onRefresh();
空实现,留给子类来初始化其他bean
注册消息监听器
registerListeners();
在所有注册的bean中查找Listener bean,注册到消息⼴播器中,见registerListeners方法
初始化非惰性单实例
finishBeanFactoryInitialization(beanFactory);
初始化剩下的单实例(非惰性的),见finishBeanFactoryInitialization方法
完成refresh后置任务
finishRefresh();
完成刷新过程,通知⽣命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别⼈,见finishRefresh方法
prepareRefresh - 准备阶段:准备环境
它的作用是准备预处理,功能包括:
记录spring容器的启动时间startupDate
标记容器为激活
初始化上下文环境如文件路径信息
验证必填属性是否填写
初始化保存事件的集合
核心代码包括:
// 在AbstractApplicationContext中是空实现,留给子类自定义个性化的属性设置方法
initPropertySources();
// 校验配置文件的属性,合法性
getEnvironment().validateRequiredProperties();
// 初始化保存事件的集合
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
在实际的工程应用中,可以通过继承ClassPathXmlApplicationContext,重写initPropertySources方法来自定义一些属性规则,例如使用以下逻辑给VAR属性添加了一条必填的验证规则:
getEnvironment().setRequiredProperties("VAR");
obtainFreshBeanFactory - 准备阶段:创建BeanFactory加载DB
它的作用包括获取BeanFactory,解析配置文件,生成beanDefinition
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
代码框架很简单,先调用refreshBeanFactory加载,然后调用getBeanFactory获取
getBeanFactory是很简单的,看AbstractRefreshableApplicationContext#getBeanFactory
中的实现:
public final ConfigurableListableBeanFactory getBeanFactory() {
DefaultListableBeanFactory beanFactory = this.beanFactory;
……
return beanFactory;
}
就是取成员变量直接获取
prepareBeanFactory - 准备阶段:准备BeanFactory功能
该方法主要负责对BeanFactory的预准备工作,配置beanFactory的基础属性,比如ClassLoader和一些PostProcessor等,包括:
设置BeanFactory的类加载器、支持表达式解析器…
添加部分BeanPostProcessor(例如ApplicationContextAwareProcessor)
设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware、xxx;
注册可以解析的自动装配;我们能直接在任何组件中自动注入:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
添加BeanPostProcessor(例如ApplicationListenerDetector)
添加编译时的AspectJ;
给BeanFactory中注册一些能用的组件;
步骤一、类加载器
//设置类加载器
beanFactory.setBeanClassLoader(getClassLoader());
首先设置类加载器,设置beanFactory的classLoader为当前context的classLoader
步骤二、表达式解析器和资源编辑注册器
//设置bean表达式解析器
if (!shouldIgnoreSpel) {
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
}
//资源编辑注册器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
表达式解析器是SpEL语言解析器。SpEL使⽤#{…}作为定界符,所有在⼤框号中的字符都将被认为是SpEL。例如以下SpEL解析器实例:
public class SpelTest {
@Test
public void test1() {
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("('Hello' + ' World').concat(#end)");
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("end", "!");
System.out.println(expression.getValue(context));
}
}
这是一个Spel解析器的实例,可以看出来其作用主要是做解析和变量填充
表达式解析器的调用点在AbstractAutowireCapableBeanFactory#populateBean
的流程中,比较深,在属性注入里面需要注入属性值,调用AbstractAutowireCapableBeanFactory#applyPropertyValues
,构造了一个BeanDefinitionValueResolver实例,在BeanDefinitionValueResolver#doEvaluate
方法中就调用了AbstractBeanFactory#evaluateBeanDefinitionString
方法,借助BeanExpressionResolver解析SpEL表达式
具体可以看:
资源编辑注册的目的是为了使spring可以解析一些非String类型的注入。
但是这里只注册了一个默认注册的ResourceEditorRegistrar,它提供了String解析成Resource、Path、Class等复杂类型的能力,但是如果是想解析别的,那就不行了,例如Date类型:
@Data
public class DateTest {
private Date date;
}
有一个属性为Date类型的DTO,需要以bean的形式注入,写xml文件如下:
<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http">
<bean id="dateTest" class="com.huawei.cbc.udrmetricservice.DateTest">
<property name="date" value="2023-12-15" />
</bean>
</beans>
这时候想要获取bean就会报错:
@Test
public void test() throws ExecutionException, IOException, ClassNotFoundException, SQLException {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
DateTest dateTest = (DateTest) ctx.getBean("dateTest");
System.out.println(dateTest);
}
// Caused by: java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.util.Date' for
// property 'date': no matching editors or conversion strategy found
// at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:262)
// at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:590)
// ... 86 more
就是因为将String类型注入date类型导致的。为了解决这类异常,spring提供了两种方案,都是基于CustomEditorConfigurer的
看CustomEditorConfigurer有两个核心属性:
@Nullable
private PropertyEditorRegistrar[] propertyEditorRegistrars;
@Nullable
private Map<Class<?>, Class<? extends PropertyEditor>> customEditors;
对应了spring提供的两种解决方案:自定义属性解析器并注册进环境、把spring预置的一些属性解析器注册进环境
自定义属性解析器
如果自定义属性解析器,则要继承PropertyEditorSupport方法,同时配置到CustomEditorConfigurer中并注入CustomEditorConfigurer的customEditors属性
PropertyEditorSupport的用法在前面也以ResourceArrayPropertyEditor为例已经看过了,最核心就是setAsText方法,将Stirng类型的注入值,做了一步转换:
例如我们自定义了DatePropertyEditor类,只需要重写setAsText即可
public class DatePropertyEditor extends PropertyEditorSupport {
private String format = "yyyy-MM-dd";
public void setFormat(String format) {
this.format = format;
}
public void setAsText(String arg0) throws IllegalArgumentException {
System.out.println("arg0: " + arg0);
SimpleDateFormat sdf = new SimpleDateFormat(format);
try {
Date d = sdf.parse(arg0);
this.setValue(d);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
然后在xml中注册
<bean class="org.Springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.util.Date">
<bean class="com.test.DatePropertyEditor">
<property name="format" value="yyyy-MM-dd"/>
</bean>
</entry>
</map>
</property>
</bean>
使用spring预置的解析器
这需要我们重写下PropertyEditorRegistrar,可以先看下spring预置的重写:ResourceEditorRegistrar,上面也看到了它加载的地方
public void registerCustomEditors(PropertyEditorRegistry registry) {
ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);
doRegisterEditor(registry, Resource.class, baseEditor);
doRegisterEditor(registry, ContextResource.class, baseEditor);
doRegisterEditor(registry, WritableResource.class, baseEditor);
doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
doRegisterEditor(registry, Path.class, new PathEditor(baseEditor));
doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));
ClassLoader classLoader = this.resourceLoader.getClassLoader();
doRegisterEditor(registry, URI.class, new URIEditor(classLoader));
doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader));
if (this.resourceLoader instanceof ResourcePatternResolver) {
doRegisterEditor(registry, Resource[].class,
new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver));
}
}
可以看出来,spring是为了注册一些可以解析Resource、Path等类型的特殊属性,里面是没有对Date类型进行解析的,因此我们做对应实现:
public class DatePropertyEditorRegistrar implements PropertyEditorRegistrar{
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat ("yyyy-MM-dd"),true));
}
}
然后通过xml注入
<bean class="org.Springframework.beans.factory.config.CustomEditorConfigurer">
<property name="propertyEditorRegistrars">
<list>
<bean class="com.test.DatePropertyEditorRegistrar"></bean>
</list>
</property>
</bean>
但是上面在prepareBeanFactory的流程中,只是硬编码加载了那个默认的ResourceEditorRegistrar,那自定义的DatePropertyEditorRegistrar是在哪里被加载到环境中的呢?通过PropertyEditorRegistrar#registerCustomEditors
向上查找调用点:
这个AbstractBeanFactory#initBeanWrapper
方法就很明确了,是在AbstractAutowireCapableBeanFactory#instantiateBean
调用的,这里就是doCreateBean核心三步骤中的第一步了,上面的调用点就是bean的加载流程
步骤三、配置aware初始化时前置处理器
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
这个ApplicationContextAwareProcessor是BeanPostProcessor的实现
class ApplicationContextAwareProcessor implements BeanPostProcessor
BeanPostProcessor前面见过,是一个bean创建时的可插入式扩展
ApplicationContextAwareProcessor实现了BeanPostProcessor#postProcessBeforeInitialization
说明它是初始化前调用的,回顾它的调用点实际上不止一个,比较典型的就是doCreateBean三步骤最后一步initializeBean
这里只加了ApplicationContextAwareProcessor一个处理器,说明了几个问题:
其他BeanPostProcessor还有其他插入点,其实就在下面registerBeanPostProcessors方法
ApplicationContextAwareProcessor是一个预置且必选的处理器
它的功能是让实现Aware接口的类具备感知能力,前面也说是,Aware是意识,即能够意识到一些东西,比如ApplicationContextAware的实现类能够意识到ApplicationContext,其实就是通过这个ApplicationContextAwareProcessor实现的
参考ApplicationContextAwareProcessor#postProcessBeforeInitialization
,点我跳转
步骤四、忽略&主动设置依赖注入
有七类bean需要在步骤三添加的postProcessBeforeInitialization 中已处理,因此忽略依赖注入:
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);
步骤五、其他的BeanPostProcessor
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!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());
}
postProcessBeanFactory - 准备阶段:空实现做BeanFactory的可选后置处理
空实现,给特殊的applicationContext用,比如GenericWebApplicationContext#postProcessBeanFactory
invokeBeanFactoryPostProcessors - 准备阶段:注册并激活BeanFactoryPostProcessor
虽然这里名字叫BeanFactoryPostProcessors,但是实际上整体流程处理了两类:BeanFactoryPostProcessors和BeanPostProcessor
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 激活BeanFactoryPostProcessor和BeanPostProcessor
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null &&
beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
// 添加一类默认的BeanPostProcessor
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
整体方法可见分成两部分,一部分调用PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
,另一部分硬编码添加了一个默认的BeanPostProcessor,同样其他BeanPostProcessor还有其他插入点,其实就在下面registerBeanPostProcessors方法
核心在PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors
方法中,点我跳转
registerBeanPostProcessors - 准备阶段:注册BeanPostProcessor
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
核心在PostProcessorRegistrationDelegate.registerBeanPostProcessors
方法中,点我跳转
initMessageSource - 准备阶段:初始化国际化资源
这一步为ApplicationContext 添加 messageSource 成员,实现国际化功能。去 beanFactory 内找名为 messageSource 的 bean,如果没有,则提供空的 MessageSource 实现
initApplicationEventMulticaster - 准备阶段:注册广播器
准备初始化应⽤消息⼴播器
spring的广播机制包括广播器AbstractApplicationEventMulticaster、事件ApplicationEvent、监听器ApplicaitonListener。用法如下:
// 定义event,必须适配ApplicationEvent中的构造方法
public class MyTest extends ApplicationEvent {
public String msg;
public MyTest (Object source) {
super(source);
}
public MyTest (Object source, String msg) {
super(source);
this.msg = msg;
}
public void print(){
System.out.println(msg);
}
}
// 定义监听器,重写onApplicationEvent方法
@Service
public class MyTest implements ApplicationListener {
public void onApplicationEvent(ApplicationEvent event) {
if(event instanceof MyTest){
MyTest testEvent = (MyTest)event;
testEvent .print();
}
}
}
// 无需实现广播器,因为spring提供了默认的,直接写事件触发流程
public class MyTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath: applicationContext.xml");
MyTest event = new MyTest("hello", "msg");
context.publishEvent(event);
}
}
可以看到这种模式即观察者模式的典型代表
再来看initApplicationEventMulticaster中的逻辑:
如果⽤户⾃定义了事件⼴播器,那么使⽤⽤户⾃定义的事件⼴播器。
如果⽤户没有⾃定义事件⼴播器,那么使⽤默认的ApplicationEventMulticaster。
默认广播器的流程在:
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() + "]");
}
}
可见这里注册的默认广播器就是SimpleApplicationEventMulticaster,这个类的具体用法参考SimpleApplicationEventMulticaster部分
onRefresh - 准备阶段:空实现
空实现,给子类做对应的功能
registerListeners - 准备阶段:注册监听器
注册监听器,上面看了广播器的注册,这里就该注册监听器了
硬编码形式注册监听器:
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
配置文件读取注册监听器:
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
注册好之后立刻激活广播器的钩子方法,让广播器开始广播event,这里同样以SimpleApplicationEventMulticaster#multicastEvent
为例,点我跳转
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
finishBeanFactoryInitialization - 初始化阶段:初始化bean
这一步会将beanFactory的成员补充完毕,并初始化所有非懒加载的bean
步骤一、加载ConversionService
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
Conversion也是一个类型转换器,作为PropertyEditor的补充存在。
前面了解过PropertyEditorSupport自定义属性解析器,这里的Conversion是spring提供的另一种属性转换的工具,而且似乎更简单一点,它的使用逻辑如下:
定义一个转换器
public class String2DateConverter implements Converter<String, Date> {
@Override
public Date convert(String arg0) {
try {
return DateUtils.parseDate(arg0, new String[] { "yyyy-MM-dd HH:mm:ss" });
} catch (ParseException e) {
return null;
}
}
}
注册bean
<bean id="conversionService" class="org.Springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="String2DateConverter" />
</list>
</property>
</bean>
测试类型转换
public void testStringToPhoneNumberConvert() {
DefaultConversionService conversionService = new DefaultConversionService();
conversionService.addConverter(new StringToPhoneNumberConverter());
String phoneNumberStr = "010-12345678";
PhoneNumberModel phoneNumber = conversionService.convert(phoneNumberStr, PhoneNumber Model.class);
Assert.assertEquals("010", phoneNumber.getAreaCode());
}
想要探究其用法,可以深入了解ConversionService#convert
方法即可
步骤二、加载内嵌值解析器
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
步骤三、初始化LoadTimeWeaverAwareTime类型的bean
// 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);
}
步骤四、冻结配置
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
步骤五、初始化非懒加载的bean
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
这里调用就到了DefaultListableBeanFactory#preInstantiateSingletons
是老熟人了
这里直接看下对应方法:
public void preInstantiateSingletons() throws BeansException {
……
for (String beanName : beanNames) {
// 1. 合并BD
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 2. 加载bean
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
……
}
else {
getBean(beanName);
}
}
}
// 3. 激活SmartInitializingSingleton扩展点
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = 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();
}
}
}
可以看到有三个步骤:
合并BD
加载bean
激活SmartInitializingSingleton扩展点
合并BD这块前面已经了解过MergedBeanDefinitionPostProcessor了
第二部分加载bean,本质上就到了前面从BeanFactory中获取bean的流程了,包括从FactoryBean中获取,和最近的获取,参考下面链接:
第三部分激活SmartInitializingSingleton扩展点,这是一个bean完全加载完后的最后一步的扩展点,可以参考以下部分:
finishRefresh - 初始化后处理:添加lifecycle成员
这一步会为 ApplicationContext 添加 lifecycleProcessor 成员,用来控制容器内需要生命周期管理的 bean。准备好生命周期管理器,就可以实现
调用 context 的 start,即可触发所有实现 LifeCycle 接口 bean 的 start
调用 context 的 stop,即可触发所有实现 LifeCycle 接口 bean 的 stop
最后再发布ContextRefreshed事件,整个refresh执行完成。
步骤一、清理类资源记录
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
DefaultResourceLoader是ResourceLoader接口的默认实现,内部维护了一个ConcurrentHashMap用来缓存class的resource。这里即清理前面记录的类资源(因为已经有了BeanDefinition)
初始化生命周期处理器
生命周期处理器是为了开启一些实现Lifecycle的bean,有明确的生命周期,激活它们的start方法,让他们开始工作,例如spring-test测试架构中的环境bean,我想启动一个内存redis服务器,就要在上下文加载完成后,启动redisServer,这里就可以利用Lifecycle的能力,让它们实现服务器自启动
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// 初始化完成激活生命周期处理器的onRefresh方法
getLifecycleProcessor().onRefresh();
发布ContextRefreshedEvent事件
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
当监听到ContextRefreshedEvent事件,就意味着环境已经启动了,可以让我们的业务代码启动了
refreshBeanFactory
继承自AbstractRefreshableApplicationContext,核心逻辑见下面:
// 为spring应用上下文对象创建我们的beanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 为容器设置一个序列号ID,可以通过反序列化获取bean工厂
beanFactory.setSerializationId(getId());
// 自定义BeanFactory
customizeBeanFactory(beanFactory);
// 加载bean定义,这里完成了对资源模糊匹配查找的实现
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
首先是创建beanFactory,如果没有特殊处理,在AbstractRefreshableApplicationContext#createBeanFactory
的实现就是创建DefaultListableBeanFactory
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
这个bean工厂前面已经见过
然后自定义bean工厂,在AbstractRefreshableApplicationContext#customizeBeanFactory
也提供了默认实现
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
这里配置了两个特性,即:
allowBeanDefinitionOverriding:是否允许覆盖同名称的不同定义的对象,它的使用位置在
DefaultListableBeanFactory#registerBeanDefinition
,点我跳转allowCircularReferences:是否允许循环依赖,它的使用位置在
AbstractAutowireCapableBeanFactory#doCreateBean
方法第一步实例化的地方,判断是否需要保留早期bean提供三级缓存,点我跳转
最后就是loadBeanDefinitions做BD加载,在此方法中仅提供了一个抽象方法,在开发场景中最常用的就是通过xml配置文件加载BD,则参考AbstractXmlApplicationContext#loadBeanDefinitions
方法
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(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);
}
在这个方法中可以看出来,就是在初始化BeanDefinitionReader,同时将ResourceEntityResolver资源解析器配置进去,它是DelegatingEntityResolver的实现,前面也见过
然后就是loadBeanDefinitions方法,其实就是调用到XmlBeanDefinitionReader#loadBeanDefinitions方法,前面也分析过其逻辑了
ApplicationContextAwareProcessor - 上下文前后置处理器
实现了BeanPostProcessor接口,但只重写了postProcessBeforeInitialization方法,并未对postProcessAfterInitialization做过多处理。
它是Aware接口实现类具备Aware能力的来源
postProcessBeforeInitialization
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;
}
非Aware接口实现类,直接返回,是的话调用invokeAwareInterfaces
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationStartupAware) {
((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
方法比较清晰,是哪一类Aware,配什么属性即可
PostProcessorRegistrationDelegate
invokeBeanFactoryPostProcessors
扫描并激活BeanFactoryPostProcessors处理器
BeanFactoryPostProcessors也是一类可插入式的处理器,用于在加载完BD和BeanFactory后,开始初始化bean之前,用于调整BD定义和BeanFactory的一类处理器,它有两类特性:
可以采用配置注册和硬编码注册
可以实现order接口控制它们的执行顺序,但是实现order接口必须采用配置注册方式
这块代码整体分为三个部分:if-else加一块独立部分
if (beanFactory instanceof BeanDefinitionRegistry) {
……
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
这一部分代码是一个if-else结构,判断条件是if (beanFactory instanceof BeanDefinitionRegistry)
因为对BeanDefinitionRegistry来说,有一部分专门的BeanFactoryPostProcessor——BeanDefinitionRegistryPostProcessor
而对于普通的BeanFactoryPostProcessor和特殊的BeanDefinitionRegistryPostProcessor,都有配置注册和硬编码注册两种注册方式,即整体代码块处理了3类注册流程,如果算上order接口,实际上流程更多
BeanDefinitionRegistry激活BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistry激活BeanFactoryPostProcessor
普通BeanFactory激活BeanFactoryPostProcessor
个人认为这块代码有很大的优化空间
为BeanDefinitionRegistry处理硬编码的BeanDefinitionRegistryPostProcessor
先看if (beanFactory instanceof BeanDefinitionRegistry)
为true的部分
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
这一块是在找硬编码注册的处理器,为什么说是硬编码,因为这里的循环对象beanFactoryPostProcessors是来自于AbstractApplicationContext#invokeBeanFactoryPostProcessors
方法中对AbstractApplicationContext#getBeanFactoryPostProcessors
的调用,点我跳转
这里对结果进行循环,找到BeanDefinitionRegistryPostProcessor,直接执行,如果是常规的BeanFactoryPostProcessor就先不执行了,添加到regularPostProcessors里面去
为BeanDefinitionRegistry处理配置的且实现PriorityOrdered接口优先级最高的BeanDefinitionRegistryPostProcessor
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, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
然后这一部分找配置成bean的BeanDefinitionRegistryPostProcessor实现,并且调用invokeBeanDefinitionRegistryPostProcessors激活这些处理器
这里注意到,有一个判断条件是if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class))
,即优先级最高
为BeanDefinitionRegistry处理配置的且实现Ordered接口优先级次高的BeanDefinitionRegistryPostProcessor
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, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
然后是配置的BeanDefinitionRegistryPostProcessor且实现Ordered接口的
这里注意到,有一个判断条件是if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class))
,即优先级次高
为BeanDefinitionRegistry处理配置的且没有实现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));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
这一部分就是优先级最低的部分了
为BeanDefinitionRegistry处理硬编码和配置的BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
最后再把配置和硬编码的BeanFactoryPostProcessor激活一下
为普通BeanFactory处理硬编码的BeanFactoryPostProcessor
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
为普通BeanFactory处理配置的BeanFactoryPostProcessor
也是对实现PriorityOrdered、Ordered、没实现Ordered的三类处理,不再细分
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
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);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 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));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
最后清理缓存
beanFactory.clearMetadataCache();
invokeBeanDefinitionRegistryPostProcessors
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
.tag("postProcessor", postProcessor::toString);
postProcessor.postProcessBeanDefinitionRegistry(registry);
postProcessBeanDefRegistry.end();
}
}
执行postProcessBeanDefinitionRegistry,比较简单
invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory)
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();
}
}
执行postProcessBeanFactory方法,比较简单
beanFactoryPostProcessor的实现案例
前面说过,beanFactoryPostProcessor可以用于修改beanDefinition,例如有一个bean记录连接密码:
<bean id="simpleBean" class="com.Spring.ch04.SimplePostProcessor">
<property name="connectionString" value="bollocks"/>
<property name="password" value="imaginecup"/>
<property name="username" value="Microsoft"/>
</bean>
想要去除属性的输出,可以实现BeanFactoryPostProcessor
public class MyTest implements BeanFactoryPostProcessor {
private Set<String> obscenties;
public MyTest() {
this.obscenties = new HashSet<String>();
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
StringValueResolver valueResover = new StringValueResolver() {
public String resolveStringValue(String strVal) {
if (isObscene(strVal)) return "*****";
return strVal;
}
};
BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResover);
visitor.visitBeanDefinition(bd);
}
}
public boolean isObscene(Object value) {
String potentialObscenity = value.toString().toUpperCase();
return this.obscenties.contains(potentialObscenity);
}
public void setObscenties(Set<String> obscenties) {
this.obscenties.clear();
for (String obscenity : obscenties) {
this.obscenties.add(obscenity.toUpperCase());
}
}
}
现在配置bean的注册方式,在xml中给obscenties配置好
<bean id="bfpp" class="com.Spring.ch04.ObscenityRemovingBeanFactoryPostProcessor">
<property name="obscenties">
<set>
<value>bollocks</value>
<value>winky</value>
<value>bum</value>
<value>Microsoft</value>
</set>
</property>
</bean>
这样在加载simpleBean的时候就可以自动屏蔽掉符合配置的value
ConfigurableListableBeanFactory bf=new XmlBeanFactory(new ClassPathResource("/METAINF/BeanFactory.xml"));
BeanFactoryPostProcessor bfpp = (BeanFactoryPostProcessor)bf.getBean("bfpp");
bfpp.postProcessBeanFactory(bf);
System.out.println(bf.getBean("simpleBean"))
PropertySourcesPlaceholderConfigurer类是用来解析占位符的,就是一个典型应用
registerBeanPostProcessors
注册BeanPostProcessor,在前面几个方法中都通过直接调用add方法硬编码了几个BeanPostProcessor,但毕竟不是通用方法,这里对大部分自定义BeanPostProcessor做了统一处理,
前面了解过它是一个bean创建时的可插入式扩展
它的调用点实际上不止一个,比较典型的就是doCreateBean三步骤最后一步initializeBean
BeanPostProcessor也有一个子接口:MergedBeanDefinitionPostProcessor,它的作用是处理MergedBeanDefinition,但是在spring代码中并没有一个叫MergedBeanDefinition的类,因为它其实是一个抽象意义,代表父子BD合并之后的混合BeanDefinition,它也在这里做了处理
回来看该方法,和上面invokeBeanFactoryPostProcessors方法逻辑基本一致,也对Ordered接口做了适配:
首先对BeanPostProcessor的实现按Ordered接口实现分类:
分成了PriorityOrdered、Ordered和没有Ordered三类,同时从PriorityOrdered里面筛选出了MergedBeanDefinitionPostProcessor,然后第一个加载PriorityOrdered实现类
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);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
第二个加载Ordered的实现,同时从Ordered里面筛选出了MergedBeanDefinitionPostProcessor
// 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);
第三个加载非Ordered,同时筛选出了MergedBeanDefinitionPostProcessor
// 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);
最后再加载MergedBeanDefinitionPostProcessor
// Finally, re-register all internal BeanPostProcessors.
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));
回看该方法,可以总结出与invokeBeanFactoryPostProcessors方法的一些异同:
相似点:都是对注册和硬编码两类做处理,都有各自的子类处理器,例如BeanFactoryPostProcessor的BeanDefinitionRegistryPostProcessor、BeanPostProcessor的MergedBeanDefinitionPostProcessor
不同点:BeanFactoryPostProcessor的处理注册连带调用,对于硬编码处理的目的也是提前和调用;BeanPostProcessor是只注册,在后面初始化的时候才调用,硬编码的处理也只是spring为了注册一些特殊的BeanPostProcessor,不提倡用户自行硬编码注册
registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors)
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);
}
}
}
执行addBeanPostProcessor方法,比较简单
SimpleApplicationEventMulticaster - 默认事件广播器
成员变量
成员变量比较简单:
// 线程池,用于并发启动监听者的onApplicationEvent操作,可见监听方收到事件是并行执行的
private Executor taskExecutor;
private ErrorHandler errorHandler;
private volatile Log lazyLogger;
multicastEvent
广播的核心方法,在AbstractApplicationContext#refresh
流程中触发
一个特别显眼的就是在AbstractApplicationContext#refresh
方法的registerListeners中,说明前面注册完了广播器,后面注册监听器时,就会触发广播。另外在AbstractApplicationContext#start
、AbstractApplicationContex#stop
方法中也会直接触发
广播中最核心的部分就是调用getApplicationListeners方法获得并遍历ApplicationListeners,分别起线程执行invokeListerner方法。进而调用到doInvokeListener
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,否则遍历执行invokeListener
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
invokeListener
事件广播实际上是触发监听器的onApplicationEvent方法。从这个方法中就很容易看出了。
从invokeListner方法中调用到doInvokeListner后,
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
……
调用监听器的onApplicationEvent方法
所以spring事件广播机制的逻辑其实就是实现监听器的onApplication方法,监听对应事件即可
DefaultLifeCycleProcessor - 默认生命周期处理器
成员变量
// LifeCycle管理组中的成员
private final List<LifecycleGroupMember> members = new ArrayList<>();
onRefresh
public void onRefresh() {
startBeans(true);
this.running = true;
}
startBeans - 上下文启动入口
private void startBeans(boolean autoStartupOnly) {
// 找到所有的Lifecycle实现类
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new TreeMap<>();
// 存入LifecycleGroup
lifecycleBeans.forEach((beanName, bean) -> {
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
int startupPhase = getPhase(bean);
phases.computeIfAbsent(startupPhase,
phase -> new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly)
).add(beanName, bean);
}
});
// 调用start方法
if (!phases.isEmpty()) {
phases.values().forEach(LifecycleGroup::start);
}
}
start
public void start() {
……
for (LifecycleGroupMember member : this.members) {
doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);
}
}
继续向下看
doStart
private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {
Lifecycle bean = lifecycleBeans.remove(beanName);
if (bean != null && bean != this) {
……
try {
bean.start();
}
catch (Throwable ex) ……
}
}
}
这里就看到了,激活Lifecycle生命周期bean的start方法,从而做一些bean的开始和销毁工作
评论区