Spring容器的启动流程
1、扫描并注册BeanDefinition:
- Spring 会开始扫描指定的包,查找带有 @Component、@Service、@Repository 和 @Controller 等注解的类。
- 发现的类会被处理,创建相应的 BeanDefinition 对象,封装类名、作用域、依赖关系等元数据。
- 这些 BeanDefinition 对象会被注册到 BeanDefinitionRegistry 中,构建容器对应用组件的理解。
2、解析配置和Bean装配:
- Spring 也会处理带有 @Configuration 注解的配置类,识别带有 @Bean 注解的方法。
- 这些方法的返回值被视为 bean 定义,类似于扫描到的组件一样进行处理。
- 这一步确保通过 Java 配置定义的 bean 也会被注册到容器中。
3、创建非懒加载的单例Bean:
- 容器开始创建非懒加载的单例 bean,包括实例化和依赖注入。
- 依赖关系通过构造函数注入、setter 方法或字段注入来解析,确保每个 bean 都正确注入了依赖。
4、Bean的创建生命周期:
- Bean 的创建包括多个步骤,如合并 bean 定义、推断构造函数、实例化、属性填充、预初始化、初始化和后初始化。
- 初始化后,面向切面编程(AOP)框架开始起作用,允许横切关注点被编织到 bean 中。
5、发布容器启动事件:
- 一旦非懒加载的单例 bean 被创建和初始化,Spring 会发布 ContextRefreshedEvent 事件。
- 此事件表示容器已完全初始化,允许其他组件在启动后执行操作。
- 其中会调用Refresh()方法:
// 1. 刷新前的预处理prepareRefresh();// 2. 获取 beanFactory,即前面创建的【DefaultListableBeanFactory】ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 3. 预处理 beanFactory,向容器中添加一些组件prepareBeanFactory(beanFactory);try {// 4. 子类通过重写这个方法可以在 BeanFactory 创建并与准备完成以后做进一步的设置postProcessBeanFactory(beanFactory);// 5. 执行 BeanFactoryPostProcessor 方法,beanFactory 后置处理器invokeBeanFactoryPostProcessors(beanFactory);// 6. 注册 BeanPostProcessors,bean 后置处理器registerBeanPostProcessors(beanFactory);// 7. 初始化 MessageSource 组件(做国际化功能;消息绑定,消息解析)initMessageSource();// 8. 初始化事件派发器,在注册监听器时会用到initApplicationEventMulticaster();// 9. 留给子容器(子类),子类重写这个方法,在容器刷新的时候可以自定义逻辑,web 场景下会使用onRefresh();// 10. 注册监听器,派发之前步骤产生的一些事件(可能没有)registerListeners();// 11. 初始化所有的非单实例 beanfinishBeanFactoryInitialization(beanFactory);// 12. 发布容器刷新完成事件finishRefresh();
6、延迟加载的Bean创建:带有 @Lazy 标记的 bean 不会在初始启动过程中创建,而是在首次请求时创建。这有助于优化启动时间。
7、处理应用关闭:
- Spring 注册了一个关闭钩子,在应用关闭时优雅地释放资源。
- 发布 ContextClosedEvent 并执行清理任务,确保正确处理单例 bean。
8、Spring 启动完成:所有这些步骤完成后,Spring 容器已完全初始化,并准备好处理来自应用程序的请求。启动过程结束,应用程序处于运行状态。
9、处理其他注解:在Spring启动过程中,还会处理其他注解,比如@Import等,这些注解可能会引入其他配置或者Bean到应用程序上下文中。
ps:以下是我整理的java面试资料,密码是obht,感兴趣的可以看看。最后,创作不易,觉得写得不错的可以点点关注!
链接:https://www.yuque.com/u39298356/uu4hxh?# 《Java面试宝典》