前言
在看狂神频道的时候偶然发现下图,感触颇深。特别在当今【程序 = 业务 + 框架】思想盛行的开发者中,夯实基础基础显得格外重要,因此开此专栏总结记录。
对于Spring框架的知识,已经在学习设计模式的时候练习过一轮,接下来不断温故而知新哈哈,学习记录回顾:
SpringContext初始化流程:(需阅读源码)
详见:
-
左上角是三种类型的context:
- ClassPathXmlApplicationContext
- SpringApplicationContext
- WebApplicationContext
-
不论哪种context创建后都会调用AbstractApplicationContext 类的refresh 方法,这个方法是我们要重点分析的,在refresh 方法中:
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal BeanFactroy. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the BeanFactroy for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the BeanFactroy in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... ; } } }
- 第一步,
prepareRefresh();
-
- 首先对刷新进行准备,包括设置开始时间,设置激活状态,初始化context 环境中的占位符,这个动作根据子类的需求由子类来执行,然后验证是否缺失必要的properties
- 第二步,
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
- 刷新并获取内部的beanFactory
- 第三步,
prepareBeanFactory(beanFactory)
对Beanfactory 进行准备工作,- 比如设置类加载器和后置处理器,配置不能自动装配的类型,注册默认的环境Bean
- 第四步,
postProcessBeanFactory(beanFactory);
为context 的子类提供后置处理并factory 的扩展能力,- 如果子类想在并定义加载完成后,开始初始化上下文之前做一些特殊逻辑,可以复写这个方法
- 第五步,
invokeBeanFactoryPostProcessors(beanFactory)
执行context 中注册的BeanFactroy 后置处理器,这里有两种后置处理器:- 一种是可以注册bean 的后置处理器
- 另一种是针对BeanFactroy 进行处理的后置处理器
- 执行的顺序是先按优先级执行可注册并的处理器,然后再按优先级执行针对BeanFactroy 的处理器
- 对SpringBoot来说这一步会进行注解bean definition 的解析,流程如右面的小框中所示
- 由configuration class post processor 出发由classpathbeandefinitionscanner解析bean 注册到BeanFactroy
- 第六步,
registerBeanPostProcessors(beanFactory);
- 按优先级顺序在BeanFactroy 中注册bean 的后置处理器,Bean后置处理器可以在Bean的初始化前后执行处理
- 第七步,
initMessageSource();
- 初始化消息源,消息源用来支持消息的国际化
- 第八步,
initApplicationEventMulticaster();
- 初始化应用事件广播器。事件广播器用来向application listener 通知各种应用产生的事件,是一个标准的观察者模式
- 第九步,
onRefresh();
- 是留给子类的扩展步骤,用来让特定的context 子类来初始化其他的Bean
- 第十步,
registerListeners();
- 把实现的application listener 的bean 注册到事件广播器,并对广播器中早期没有广播的事件进行通知
- 第十一步,
finishBeanFactorylnitialization(beanFactory);
- 冻结所有的Bean人描述信息的修改实例化非延迟加载的单例Bean
- 第十二步,
finishRefresh();
- 完成上下文的刷新工作,调用LifecycleProcessor 的on fresh 方法,以及发布context refresh 的event事件
- 最后在finally 中执行第十三步,
resetCommonCaches()
重置公共的缓存,- 比如ReflectionUtils中的缓存AnnotationUtils中的缓存等等
- 至此,spring 的context 初始化就完成了,由于篇幅和时间的关系呢,这里介绍了最主要的流程,建议课后阅读源码来复习这个知识点,来补全细节
- 第一步,
Spring中Bean生命周期:(需阅读源码)
面试中经常会问到Bean人的生命周期,我们先看绿色的部分:
- Bean的创建过程:
- 首先调用Bean的构造方法创建bean,然后通过反射调用setter 方法进行属性的依赖注入,
- 第三步,如果实现了BeanNameAware接口的话,会设置Bean the name
- 第四步,如果实现了BeanfactoryAware接口,会把Beanfactory 设置给bean
- 第五步,如果实现ApplicationContextAware接口会给bean 设置application context
- 第六步,如果实现了BeanPostProcessor 接口,则执行前置的处理方法
- 第七步,实现了initialize bean 接口的话会执行after property set方法
- 第八步,执行自定义的init的方法
- 第九步,执行bean post processor 接口的后置处理方法
- 这时就完成了bean 的创建过程,那么在使用完bean 需要销毁的时候,会先执行disposable bean 接口的destroy 方法
- 然后再执行自定义的destroy 方法
这部分也建议你阅读源码来加深理解
Spring扩展接口:
这一页介绍对spring 进行定制化功能扩展时,可以选择的一些扩展点:
- BeanFactoryPostProcessor是Beanfactory 的后置处理器
- 支持在Beanfactory 标准初始化完成后,对并factory 进行一些额外处理
- 我们在讲context 初始化流程时介绍过这,这时所有的Bean的描述信息已经加载完毕
- 但是还没有进行Bean的初始化,例如,我前面提到的property placeholder configure 就是在这个扩展点上对bean 属性中的站位服务进行替换的
- BeanDefinitionRegistryPostProcessor
- 它扩展自BeanPostProcessor,在执行BeanPostProcessor的功能前提供了可以添加并定义的能力
- 允许在初始化一般的Bean前注册额外的Bean
- 例如可以在这里根据Bean的scope 创建一个新的代理Bean
- BeanPostProcessor
- 提供了在bean 初始化的之前和之后,插入自定义逻辑的能力
- 与BeanFactoryPostProcessor的区别主要是处理对象不同,BeanFactoryPostProcessor是Beanfactory 进行处理
- BeaPostProcessor是对Bean进行处理
- 上面这三个扩展点可以通过实现ordered 或者priority ordered 接口来指定执行顺序,实现priority order 接口的processor 会先于实行order 接口的执行
- ApplicationContextAware
- 可以获得application context,以及其中的Bean当需要在代码中动态获取Bean时,可以通过实现这个接口来实现
- InitializingBean
- 可以在bean 初始化完成,所有属性设置完成后执行特定的逻辑
- 例如对自动装配的属性进行验证等等
- DisposableBean
- 用于在并销毁前执行特定的逻辑
- 例如做一些回收工作等等
- ApplicationListener
- 用来监听spring 的标准事件以及自定义的事件
SpringBoot扩展:
-
SpringBoot启动流程:
- 首先要配置environment
- 然后准备context 上下文
- 包括执行application context 的后置处理器
- 初始化initialize,通知listener 处理context prepared 和contextloaded 事件
- 最后执行refresh context
- 也就是我们前面介绍过的AbstractApplicationContext 类的refresh 方法
-
SpringBoot中有两种上下文:
- 一种是bootstrap
- bootstrap 是应用程序的父上下文,也就是说bootstrap 会先于application 加载
- bootstrap 主要用于从额外的资源来加载配置信息,还可以从本地外部配置文件中解密属性
- bootstrap 里面的属性会优先加载,默认也不能被本地相同的配置覆盖
- 另一种是application
- 一种是bootstrap
-
Springboot 的注解
-
需要知道 SpringBootApplication,包含了三个注解:
-
@SpringBootConfiguration
-
@EnableAutoConfiguration
-
@ComponentScan
-
-
@SpringBootConfiguration注解里面包含了configuration 注解,也就是SpringBoot的自动配置功能
-
conditional 注解是控制自动配置的生效条件的注解
- 例如bean 或class 的存在或不存在时进行配置,当满足条件时进行配置等等
-
-
SpringBoot的几个特色模块:
- starter 是SpringBoot提供的无缝集成功能的一种方式,使用某个功能时,开发者不需要关注各种依赖库的处理,不需要具体的配置信息,由SpringBoot的自动配置进行bean 的创建:
- 例如需要使用web 功能时,只需要在依赖中引入SpringBootstarter web 即可
- actuator 是用来对应用程序进行监控和管理,通过restful API 请求,来监管审计,收集应用的运行情况
提供了一系列开发工具的支持来提高开发效率,- 例如热部署能力等等
- cli 就是命令行接口,是一个命令行工具,支持使用groovy脚本,可以快速搭建spring 原型项目
- starter 是SpringBoot提供的无缝集成功能的一种方式,使用某个功能时,开发者不需要关注各种依赖库的处理,不需要具体的配置信息,由SpringBoot的自动配置进行bean 的创建: