这两行代码其实并不难; 同学们可以自己点进去看一下; 别看到代码多就慌;
register(componentClasses);
重点看这行代码 重点!!重点!!重点!!!
refresh();
}
===================================================================
refresh():加载或刷新持久化的 配置,可能是XML文件、属性文件或关系数据库中存储的。由于这是一个启动方法,如果失败,它应 该销毁已经创建的单例,以避免暂用资源。换句话说,在调用该方法之后,应该实例化所有的单例, 或者根本不实例化单例 。
ApplicationContext关闭之后不代表JVM也关闭了,ApplicationContext是 属于JVM的,说白了ApplicationContext也是JVM中的一个对象。
在Spring的设计中,也提供可以刷新的ApplicationContext和不可以刷新的ApplicationContext
可刷新的
AbstractRefreshableApplicationContext extends AbstractApplicationContext
不可刷新的
GenericApplicationContext extends AbstractApplicationContext
AnnotationConfigApplicationContext继承的是GenericApplicationContext,所以它是不能刷新 的。 AnnotationConfigWebApplicationContext继承的是 AbstractRefreshableWebApplicationContext,所以它是可以刷的。 上面说的不能刷新是指不能重复刷新,只能调用一次refresh方法,第二次时会报错。
一下就是关键重点代码; 我前几篇文章 全部都有写; 但是可能写得不够详细;这里我们再从新写一次;
里面的代码我就不再继续累赘; 因为里面代码 我们基本上都看过一次;
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start(“spring.context.refresh”);
这里是往BeanFactory 继续set 其他属性 并且里面有一个方法是:
–initPropertySources() 该方法就是初始化property 里面的属性;
有一些属性是可以设置成必须注入的属性 我们以前再整合SpringMVC的时候 再web.xml里面就有配置;
直白一点就是一些Key Value键值对;
以下就是详细:
1记录启动时间
2可以允许子容器设置一些内容到Environment中
3验证Environment中是否包括了必须要有的属性
prepareRefresh(); --源码
进行BeanFactory的refresh,在这里会去调用子类的 refreshBeanFactory方法,
具体子类是怎么刷新的得看子类,然后再调用子类的 getBeanFactory方法,
重新得到一个BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); --源码
prepareBeanFactory(beanFactory);–源码
1:设置beanFactory的类加载器
2:设置表达式解析器:StandardBeanExpressionResolver,用来解析Spring中的表达式
3:添加PropertyEditorRegistrar:ResourceEditorRegistrar,PropertyEditor类型转化器注 册器,用来注册一些默认的PropertyEditor
4:添加一个Bean的后置处理器:ApplicationContextAwareProcessor,是一个 BeanPostProcessor,用来执行EnvironmentAware、ApplicationEventPublisherAware 等回调方法
5:添加ignoredDependencyInterface:可以向这个属性中添加一些接口,
如果某个类实现 了这个接口,并且这个类中的某些set方法在接口中也存在,
那么这个set方法在自动注入的 时候是不会执行的,比如EnvironmentAware这个接口,
如果某个类实现了这个接口,那么 就必须实现它的setEnvironment方法,
而这是一个set方法,和Spring中的autowire是冲突 的,
那么Spring在自动注入时是不会调用setEnvironment方法的,
而是等到回调Aware接 口时再来调用(注意,这个功能仅限于xml的autowire,@Autowired注解是忽略这个属性 的){
a. EnvironmentAware
b. EmbeddedValueResolverAware
c. ResourceLoaderAware
d. ApplicationEventPublisherAware
e. MessageSourceAware
f. ApplicationContextAware
g 另外其实在构造BeanFactory的时候就已经提前添加了另外三个:
h. BeanNameAware
i. BeanClassLoaderAware
j. BeanFactoryAware
}
6:添加resolvableDependencies:在byType进行依赖注入时,会先从这个属性中根据类型 找bean{
a. BeanFactory.class:当前BeanFactory对象
b. ResourceLoader.class:当前ApplicationContext对象
c. ApplicationEventPublisher.class:当前ApplicationContext对象
d. ApplicationContext.class:当前ApplicationContext对象
}
7:添加一个Bean的后置处理器:ApplicationListenerDetector,
是一个 BeanPostProcessor,用来判断某个Bean是不是ApplicationListener,
如果是则把这个 Bean添加到ApplicationContext中去,
注意一个ApplicationListener只能是单例的
8: 添加一个Bean的后置处理器:LoadTimeWeaverAwareProcessor,
是一个 BeanPostProcessor,用来判断某个Bean是不是实现了LoadTimeWeaverAware接口,
如果实现了则把ApplicationContext中的loadTimeWeaver回调setLoadTimeWeaver方法
设置给该Bean。
9:添加一些单例bean到单例池{
a. “environment”:Environment对象
b. “systemProperties”:System.getProperties()返回的Map对象
c. “systemEnvironment”:System.getenv()返回的Map对象
}
try {
提供给AbstractApplicationContext的子类进行扩 展,具体的子类,可以继续向BeanFactory中再添加一些东西
postProcessBeanFactory(beanFactory); --源码
记录beanPostProcess 创建时间
StartupStep beanPostProcess = this.applicationStartup.start(“spring.context.beans.post-process”); --源码
invokeBeanFactoryPostProcessors(beanFactory);–源码
执行BeanFactoryPostProcessor{
1:此时在BeanFactory中会存在一个BeanFactoryPostProcessor: ConfigurationClassPostProcessor,它也是一个 BeanDefinitionRegistryPostProcessor
2:从BeanFactory中找到类型为BeanDefinitionRegistryPostProcessor的beanName,也就 是ConfigurationClassPostProcessor, 然后调用BeanFactory的getBean方法得到实例 对象
3:执行**ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry()**方法:[
a. 解析AppConfig类
b. 扫描得到BeanDefinition并注册
c. 解析@Import,@Bean等注解得到BeanDefinition并注册
d. ConfigurationClassPostProcessor是如何工作的 放到下个篇章 这里留个坑
e. 在这里,我们只需要知道在这一步会去得到BeanDefinition,而这些BeanDefinition中 可能存在BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,所以 执行完ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry()方 法后,还需要继续执行其他BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法
]
4:执行其他BeanDefinitionRegistryPostProcessor的 **postProcessBeanDefinitionRegistry()**方法
5:执行所有BeanDefinitionRegistryPostProcessor的**postProcessBeanFactory()**方法
6:从BeanFactory中找到类型为BeanFactoryPostProcessor的beanName,而这些 BeanFactoryPostProcessor包括了上面的BeanDefinitionRegistryPostProcessor
7:执行还没有执行过的BeanFactoryPostProcessor的**postProcessBeanFactory()**方法
}
因为上面的步骤完成了扫描,这个过程中程序员 可能自己定义了一些BeanPostProcessor,
在这一步就会把BeanFactory中所有的 BeanPostProcessor找出来并实例化得到一个对象,
并添加到BeanFactory中去(属性 beanPostProcessors),
最后再重新添加一个ApplicationListenerDetector对象(之前其实就添加了过,
这里是为了把ApplicationListenerDetector移动到最后)
registerBeanPostProcessors(beanFactory);–源码
到此,所有的BeanFactoryPostProcessor的逻辑都执行完了,主要做的事情就是得到 BeanDefinition并注册到BeanFactory中
beanPostProcess.end();–源码
如果BeanFactory中存在一个叫做"messageSource"的 BeanDefinition,那么就会把这个Bean对象创建出来并赋值给ApplicationContext的 messageSource属性,让ApplicationContext拥有国际化的功能
initMessageSource();–源码
如果BeanFactory中存在一个叫 做"applicationEventMulticaster"的BeanDefinition,
那么就会把这个Bean对象创建出来并 赋值给ApplicationContext的applicationEventMulticaster属性,
让ApplicationContext拥有 事件发布的功能
initApplicationEventMulticaster();–源码
提供给AbstractApplicationContext的子类进行扩展,没用
onRefresh();–源码
从BeanFactory中获取ApplicationListener类型的beanName,
然后添加 到ApplicationContext中的事件广播器applicationEventMulticaster中去,
到这一步因为 FactoryBean还没有调用getObject()方法生成Bean对象,
所以这里要在根据类型找一下 ApplicationListener,记录一下对应的beanName
registerListeners();–源码
完成BeanFactory的初始化,主要就是实例化 非懒加载的单例Bean
finishBeanFactoryInitialization(beanFactory);–源码
finishRefresh();–源码
BeanFactory的初始化完后,就到了Spring启动的最后一步了
设置ApplicationContext的lifecycleProcessor,默认情况下设置的是 DefaultLifecycleProcessor
调用lifecycleProcessor的onRefresh()方法,如果是DefaultLifecycleProcessor,那么会获取所 有类型为Lifecycle的Bean对象,然后调用它的start()方法,这就是ApplicationContext的生命 周期扩展机制
发布ContextRefreshedEvent事件
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
destroyBeans();
cancelRefresh(ex);
throw ex;
}
finally {
resetCommonCaches();
contextRefresh.end();
}
}
}
======================================================================================
-
执行通过ApplicationContext添加进来的BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法
-
执行BeanFactory中实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法
-
执行BeanFactory中实现了Ordered接口的BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法
-
执行BeanFactory中其他的BeanDefinitionRegistryPostProcessor的 postProcessBeanDefinitionRegistry()方法
-
执行上面所有的BeanDefinitionRegistryPostProcessor的postProcessBeanFactory()方法
-
执行通过ApplicationContext添加进来的BeanFactoryPostProcessor的 postProcessBeanFactory()方法
-
执行BeanFactory中实现了PriorityOrdered接口的BeanFactoryPostProcessor的 postProcessBeanFactory()方法
-
执行BeanFactory中实现了Ordered接口的BeanFactoryPostProcessor的 postProcessBeanFactory()方法
-
执行BeanFactory中其他的BeanFactoryPostProcessor的postProcessBeanFactory()方法
至此 Spring启动就算彻底完成;
seeyou
最后
针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。
最新整理面试题
上述的面试题答案都整理成文档笔记。也还整理了一些面试资料&最新2021收集的一些大厂的面试真题
最新整理电子书
最新整理大厂面试文档
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
最后
针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。
最新整理面试题
[外链图片转存中…(img-7c11Yo2M-1714472371780)]
上述的面试题答案都整理成文档笔记。也还整理了一些面试资料&最新2021收集的一些大厂的面试真题
最新整理电子书
[外链图片转存中…(img-jsSaOhF5-1714472371780)]
最新整理大厂面试文档
[外链图片转存中…(img-x7FelshI-1714472371781)]
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。