highlight: androidstudio
上一篇我们聊了Springboot的run方法,今天我们聊下关于容器刷新(refresh)
本文很长,请各位同学要忍一下~~~
好了,废话不多说,直接开干 !!!
1.refresh 主方法 (重要)
``` java public void refresh() throws BeansException, IllegalStateException { //加锁 防止出现其他线程也来刷新容器 synchronized(this.startupShutdownMonitor) { // 1.1 上下文刷新前的一些准备工作。如记录容器的启动时间、标记“已启动”状态、处理配置文件中的占位符等 this.prepareRefresh(); /* 1.2 创建 BeanFactory(DefaultListableBeanFactory) 并设置序列化id, 其用来加载 Bean 定义、注册 Bean 等 */ ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); // 1.3 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean this.prepareBeanFactory(beanFactory);
try {
/*
1.4
允许在上下文 子类中对 beanFactory进行 (后置处理)
【这里需要知道 BeanFactoryPostProcessor 这个知识点,Bean 如果实现了此接口,
那么在容器初始化以后,Spring 会负责调用里面的 postProcessBeanFactory 方法。】
这里是提供给子类的扩展点,到这里的时候,所有的 Bean 都加载、注册完成了,但是都还没有初始化
具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事
*/
this.postProcessBeanFactory(beanFactory);
//1.5 Bean工厂的后置处理器,BeanFactoryPostProcessor(触发时机:bean定义 注册之后; bean实例化之前)
//简单来说就是调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
this.invokeBeanFactoryPostProcessors(beanFactory);
// 1.6 注册 BeanPostProcessor 的实现类,注意看和 BeanFactoryPostProcessor 的区别
// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意,到这里 Bean 还没初始化
this.registerBeanPostProcessors(beanFactory);
//国际化相关 (略)
this.initMessageSource();
//1.7 初始化当前 ApplicationContext 的事件广播器 (略)
this.initApplicationEventMulticaster();
//1.8 具体的子类可以在这里初始化一些特殊的 Bean
this.onRefresh();
//1.9 注册事件监听器,监听器需要实现 ApplicationListener 接口 (略)
this.registerListeners();
//2.0 初始化所有的 singleton beans(lazy-init 的除外)(重要)
this.finishBeanFactoryInitialization(beanFactory);
// 发布 ApplicationContext 初始化完成事件
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
//销毁bean
this.destroyBeans();
//清除缓存
this.cancelRefresh(var9);
//抛出异常
throw var9;
} finally {
//重置 Spring 中的常见内省缓存,因为我们可能不再需要单例 bean 的元数据......
this.resetCommonCaches();
}
}
} ```
2. 接下来 将把以上流程展开
1.1 prepareRefresh
上下文刷新前的一些准备工作。如记录容器的启动时间、标记“已启动”状态、处理配置文件中的占位符等
```java protected void prepareRefresh() { // 记录启动时间 this.startupDate = System.currentTimeMillis(); this.closed.set(false); // 标记状态 this.active.set(true); if (this.logger.isDebugEnabled()) { if (this.logger.isTraceEnabled()) { this.logger.trace("Refreshing " + this); } else { this.logger.debug("Refreshing " + this.getDisplayName()); } }this.initPropertySources(); //校验必须配置 this.getEnvironment().validateRequiredProperties(); if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet(this.applicationListeners); } else { this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); }
this.earlyApplicationEvents = new LinkedHashSet(); } ```
1.2 obtainFreshBeanFactory
创建 BeanFactory(DefaultListableBeanFactory) 并设置序列化id,其用来加载 Bean 定义、注册 Bean 等
java protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // 关闭旧的 BeanFactory (如果有),创建新的 BeanFactory(DefaultListableBeanFactory) 并设置序列化id,其用来加载 Bean 定义、注册 Bean 等 this.refreshBeanFactory(); // getBeanFactory BeanFactory实际为 DefaultListableBeanFactory 。 return this.getBeanFactory(); }
这里我们附一张 DefaultListableBeanFactory 类图,关于他 可以自行谷歌一下
1.3 prepareBeanFactory
设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean (prepareBeanFactory)
```java protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { //设置类加载器 beanFactory.setBeanClassLoader(this.getClassLoader()); //beanFactory的表达式语言处理器,Spring3增加了表达式语言的支持,
//默认可以使用#{bean.xxx}的形式来调用相关属性值 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); //设置PropertyEditorRegistrar,通过PropertyEditor将xml解析出来的bean属性(字符串)和相应的java类型做转换 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
/*
添加后置处理器ApplicationContextAwareProcessor,在Bean初始化后自动执行各Aware接口的set方法
实现了 Aware 接口的 beans 在初始化的时候,这个 processor 将会回调,
这个我们很常用,如我们会为了获取 ApplicationContext 而 implement ApplicationContextAware
注意:它不仅仅回调 ApplicationContextAware,
还会负责回调 EnvironmentAware、ResourceLoaderAware 等,看下源码就清楚了
*/
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//忽略依赖了这几个接口的bean
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
/*
为特殊的几个 bean 赋值
包括BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
*/
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
//在 bean 实例化后,如果是 ApplicationListener 的子类,
//那么将其添加到 listener 列表中,可以理解成:注册 事件监听器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
//如果存在loadTimeWeaver这个Bean,则增加对应的后置处理器
if (beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
//添加默认的系统环境bean (如果没有的话)
if (!beanFactory.containsLocalBean("environment")) {
beanFactory.registerSingleton("environment", this.getEnvironment());
}
if (!beanFactory.containsLocalBean("systemProperties")) {
beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean("systemEnvironment")) {
beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
}
} ```
1.4 postProcessBeanFactory (后置处理器)
java //空方法 专门为子类提供用于扩展 ,此时所有的 Bean 都加载、注册完成了,但是都还没有初始化, //这一步可以修改 bean 定义或者增加自定义的 bean。 protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { }
此时所有的 Bean 都加载、注册完成了,但是都还没有初始化
1.5 invokeBeanFactoryPostProcessors (重要)
- 该方法作用:
调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法
- 如何扩展? :
(可以实现 BeanDefinitionRegistryPostProcessor接口 和 BeanFactoryPostProcessor接口 来扩展)
```java protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { //开始执行beanFactoryPostProcessor对应实现类,需要知道的是beanFactoryPostProcessor是spring的扩展接口,在刷新容器之前,该接口可以用来修改bean元数据信息 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors()); if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); }
} ```
紧接着我们看看 invokeBeanFactoryPostProcessors 做了什么
```java public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
Set processedBeans = new HashSet<>();
//可以看到 这个方法是先处理 BeanDefinitionRegistryPostProcessor的实现, //然后再处理BeanFactoryPostProcessor的实现, //这也是为什么我们定义的扩展点 BeanDefinitionRegistryPostProcessorPoint先打印, //BeanFactoryPostProcessorPoint后打印的原因 if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List regularPostProcessors = new ArrayList<>(); List registryProcessors = new ArrayList<>(); //开始遍历三个内部类,如果属于BeanDefinitionRegistryPostProcessor子类,加入到bean注册的集合,否则加入到regularPostProcessors for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registry