一句话总结
Spring的启动主要包括初始化和refresh()两个步骤!
初始化
// 初始化容器
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
// 注册 Spring 内置后置处理器的 BeanDefinition 到容器
this();
// 注册配置类 BeanDefinition 到容器
register(annotatedClasses);
// 加载或者刷新容器中的Bean
refresh();
}
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
流程总结
- 调用父类构造器,创建了DefaultListableBeanFactory。
- 调用自己的this()方法,创建了两个对象AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner:
- AnnotatedBeanDefinitionReader是注解配置读取器。在进行该对象创建时,会向容器中添加6个BeanDefinition,其中有两个比较重要:ConfigurationClassPostProcessor(一个BeanFactoryPostProcessor,用于将配置类中的Bean的BeanDefinition注册到容器中,同时@Import、@ComponentScan等注解也是在这里做的处理)、AutowiredAnnotationBeanPostProcessor(一个BeanPostProcessor,用于处理@Autowired的自动注入,例如当creatBean时调用构造器通过反射实例化对象时,如果使用了@Autowired就会进行自动注入)。
- ClassPathBeanDefinitionScanner是路径扫描器,用于对指定的包目录进行扫描查找 bean 对象,然后为其创建BeanDefinition对象并进行注册。在创建这个对象时,会创建默认的过滤器(如:添加了注解类型的过滤器AnnotationTypeFilter(Component.class)),使得在进行包扫描的时候将指定条件的类的BeanDefinition添加到容器中,而对其它的类不这么干。
- 调用AnnotatedBeanDefinitionReader的register方法将用户传入的 Spring 配置类解析成一个 BeanDefinition 然后注册到容器中。
refresh函数
- AbstractApplicationContext#refresh:源码
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 刷新前的预处理
prepareRefresh();
// 2. 获取 beanFactory,即前面创建的【DefaultListableBeanFactory】
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 预处理 beanFactory,向容器中添加一些组件
prepareBeanFactory(beanFactory);
try {
// 4. 子类通过重写这个方法可以在 BeanFactory 创建并与准备完成以后做进一步的设置
postProcessBeanFactory(beanFactory);
// 5. 执行 BeanFactoryPostProcessor 方法,beanFactory 后置处理器
*在BeanFactory标准初始化之后执行每个BeanFactoryPostProcessor
实现类的postProcessBeanFactory,
值得注意的是ConfigurationClassPostProcessor就是在这里执行的
将我们通过注解配置的Bean解析成BeanDefinition并注册到容器中*
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册 BeanPostProcessors,bean 后置处理器
*这一步是向容器中注册BeanPostProcessor(会通过其BeanDefinition创建出Bean,然后让
beanFactory统一进行管理),
BeanPostProcessor会干预 Spring 初始化 bean 的流程,从而完成代理、自动注入等各种功能。
同样也存在顺序上的问题:先注册实现了PriorityOrdered接口的BeanPostProcessor,
然后是实现了Ordered接口的,然后是剩下所有的普通的BeanPostProcessor,
最后还会将实现了MergedBeanDefinitionPostProcessor接口
的BeanPostProcessor再注册一遍。*
registerBeanPostProcessors(beanFactory);
// 7. 初始化 MessageSource 组件(做国际化功能;消息绑定,消息解析)
初始化 MessageSource 组件,做国际化的处理。
initMessageSource();
// 8. 初始化事件派发器,在注册监听器时会用到
初始化事件广播器,如果用户配置了就用自定义的,如果没有就创建一个SimpleApplicationEventMulticaster
initApplicationEventMulticaster();
// 9. 留给子容器(子类),子类重写这个方法,在容器刷新的时候可以自定义逻辑,web 场景下会使用
onRefresh();
// 10. 注册监听器,派发之前步骤产生的一些事件(可能没有)
将容器中所有的ApplicationListener都注册到容器中,由容器统一管理。
然后通过事件广播器发布之前步骤产生的事件ApplicationEvent。
registerListeners();
// 11. 初始化所有的非单实例 bean
初始化剩下所有的非懒加载的单例Bean对象,具体来说就是遍历所有的beanName,然后调用getBean(beanName)方法来创建Bean对象。值得注意的是,如果该Bean是FactoryBean类型,会调用两次getBean方法,第一次是将其当作普通Bean来创建,第二次是将其当作工厂,通过它来创建对象。
getBean的流程请参考这篇文章:https://blog.csdn.net/zhang_qing_yun/article/details/120083309
finishBeanFactoryInitialization(beanFactory);
// 12. 发布容器刷新完成事件
首先初始化生命周期处理器,如果用户没有配置则提供一个默认的DefaultLifecycleProcessor。然后发布容器刷新完毕的事件。
finishRefresh();
}
...
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
清空启动过程中产生的一些缓存,例如:反射相关的信息、注解相关的信息、类加载器相关的信息等,因为不再需要单例Bean的元数据了。
resetCommonCaches();
}
}
}
参考
- https://blog.csdn.net/zhang_qing_yun/article/details/120157047