BeanFactory 继承图
Spring Boot 中 ApplicationContext 的继承图
挺有意思、顶层接口、Configurable、Abstract,然后下面就是比较具体场景的实现类,Environment 也是这样的结构。
- ApplicationContext
- ConfigurableApplicationContext
- AbstractApplicationContext
- GenericApplicationContext
- GenericWebApplicationContext
- ServletWebServerApplicationContext
- AnnotationConfigServletWebServerApplicationContext & XmlServletWebServerApplicationContext
Spring 中 ApplicationContext的继承图
源码分析
ClassPathXmlApplicationContext classPathXmlApplicationContext =
new ClassPathXmlApplicationContext("coderLi.xml");
<bean class="com.demo.data.Cat" id="cat"/>
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
将要放入 Spring 的资源文件也就是 beanDefinition 解释之后赋值给 configLocations 变量保存
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}
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
protected String resolvePath(String path) {
return getEnvironment().resolveRequiredPlaceholders(path);
}
@Override
public ConfigurableEnvironment getEnvironment() {
if (this.environment == null) {
this.environment = createEnvironment();
}
return this.environment;
}
protected ConfigurableEnvironment createEnvironment() {
return new StandardEnvironment();
}
resolvePath
会搜寻匹配系统变量并进行替换。关于 Environment 的可以看我另一篇文章:Environment 概述
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
} catch (BeansException ex) {
destroyBeans();
cancelRefresh(ex);
throw ex;
} finally {
resetCommonCaches();
}
}
}
- prepareRefresh 准备刷新的上下文环境
- obtainFreshBeanFactory 创建 beanfactory 并加载注册 beanDefinition
- prepareBeanFactory 对 beanFactory 各种功能进行填充
- invokeBeanFactoryPostProcessors 对 BeanFactoryPostProcessor的bean 进行回调
- registerBeanPostProcessors 注册 BeanPostProcessors 到 BeanFactory 中
- initMessageSource 国际化
- initApplicationEventMulticaster 创建事件广播器
- onRefresh 空方法、给子类扩展
- registerListeners 注册事件监听器
- finishBeanFactoryInitialization 初始化剩下的单例 非延迟初始化的
- finishRefresh 完成刷新、通知生命周期处理器 lifecycleProcessor 刷新过程、并发布 contextRefreshEvent
- resetCommonCaches 清理使用到的一些内存缓存
prepareRefresh
protected void prepareRefresh() {
// .......
// 初始化属性源
initPropertySources();
// 对属性进行验证
getEnvironment().validateRequiredProperties();
}
initPropertySources 这个方法默认是空方法、交由子类去扩展。在 GenericWebApplicationContext 中、就将原来放入 Environment 对象中的 Servlet Context 和 Servlet Config 两个属性源占位符进行替换。详细可以看 Environment 概述
@Override
protected void initPropertySources() {
ConfigurableEnvironment env = getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null);
}
}
obtainFreshBeanFactory
@Override
protected final void refreshBeanFactory() throws BeansException {
.........
try {
// 创建 DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 为了序列化的时候、指定 id
beanFactory.setSerializationId(getId());
// 定制 beanFactory
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
.....
}
}
createBeanFactory 去创建 DefaultListableBeanFactory。
customizeBeanFactory 主要去设置两个属性、一个是是否允许 BeanDefinition 覆盖。一个是是否允许循环依赖。
loadBeanDefinitions
将第一步处理好的资源文件路径拿出来进行读取和注册到 BeanDefinitionRegister 中。
prepareBeanFactory
-
设置 BeanClassLoader、默认是获取线程中的 ClassLoader
Thread.currentThread().getContextClassLoader();
-
设置 SPEL 的解释器
-
增加一个属性编辑器的注册点
-
实现 Aware 接口的注入功能。
-
然后就是
ignoreDependencyInterface
-
registerResolvableDependency
绑定注入类型和对应的 bean -
增加一个 BeanPostProcessor、这个类主要做了一件事就是将 ApplicationListener 对象加入到 ApplicationContext 中保存起来
往后就是完 BeanFactory 中塞一些对象
所以我们可以通过注解到方式获取对象的对象
postProcessBeanFactory
默认实现方法是空实现、可以在这个方法内对 beanFactory 对一些信息进行修改、这个时机、刚刚好是所有 BeanDefinition 注册完毕、但是没有被实例化。你可以在这个方法中增加 BeanPostProcessor等。
看看其中的一两个子类实现
这个类似于上面的 ApplicationContextAwareProcessor 的功能。
另一个子类、做的事情也是类似的、BootstrapContextAwareProcessor 使用的比较少、有机会再看看吧后续。
invokeBeanFactoryPostProcessors
看名字就可以猜出是激活 BeanFactoryPostProcessor 的
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
直接进入 PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors 方法
代码很长、大概说一下流程
首先判断beanFactory是否是 BeanDefinitionRegistry 、如果是则则判断参数重的 BeanFactoryPostProcessor是否 BeanDefinitionRegistryPostProcessor、如果是则调用 postProcessBeanDefinitionRegistry 方法。
后续则去 BeanFactory中找出对应的 BeanDefinitionRegistryPostProcessor 实例、这其中先是 PriorityOrdered 的、然后是 Ordered 的、最后是正常的。
然后才是去去调用 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法。
最后也是类似的去 beanFactory 中找 BeanFactoryPostProcessor 的实例。这其中先是 PriorityOrdered 的、然后是 Ordered 的、最后是正常的。
流程上不复杂、考虑的情况有点多、所以代码篇幅有点长。
registerBeanPostProcessors
这个方法也是类似的、从 beanFactory 中捞对应的bean 出来注册然后注册、顺序 方面也是 PriorityOrdered然后Ordered、然后正常。里面也涉及到了对 MergedBeanDefinitionPostProcessor 的注册、其实它是 BeanPostProcessor的子类。
initMessageSource
初始化消息资源、国际化相关的,不太熟悉
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
} else {
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
}
}
initApplicationEventMulticaster
注册一个事件广播器、这个也没啥说的
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
} else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}
onRefresh
模版方法、给子类去扩展的方法。
registerListeners
注册监听器
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);
}
}
}
finishBeanFactoryInitialization
这个方法主要去初始化剩下非延迟初始化的 bean。
涉及到 ConversionService 、以及冻结 BeanDefinition、最后去调用 BeanFactory 的 preInstantiationSingletons方法
这个方法主要是获取所有的 BeanDefinition 然后调用 getBean 方法去实例化。如果是 FactoryBean 则会根据是否是 eager 去判断是否获取实际的 Bean。
最后会去对实现了 SmartInitializingSingleton 的回调接口。
finishRefresh
- 清理 Resource 资源
- 初始化 LifecycleProcessor
- 调用 LifecycleProcessor 的 on Refresh 方法
- 发布 ContextRefreshEvent
resetCommonCaches
这个方法在 finally 代码块中。主要是清理各种缓存资源,比如说 Spring 自定义了一个 Introspector 的检查。还有各种的其他缓存。
总结
其实整一个 refresh 过程还是挺简单的、从大体上来看、与我们直接使用 BeanFactory 的时候相比、多了一些扩展性的东西、但是这些扩展的地方、都是原本Spring 提供给我们、我们自己也可以进行扩展的。