Spring启动流程的主要步骤及对应的代码如下:
- 启动入口,从main方法调用
SpringApplication.run
。public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
- 初始化,创建
SpringApplication
实例,并设置初始化器和监听器。public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) { return new SpringApplication(primarySource).run(args); } public SpringApplication(Object... sources) { initialize(sources); } private void initialize(Object[] sources) { this.sources = new LinkedHashSet<>(Arrays.asList(sources)); this.initializers = getSpringFactoriesInstances(ApplicationContextInitializer.class); this.listeners = getSpringFactoriesInstances(ApplicationListener.class); }
- 配置环境,准备Spring环境,如读取配置文件、系统属性等。
public ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) { // 创建并配置环境 ConfigurableEnvironment environment = getOrCreateEnvironment(); configureEnvironment(environment, applicationArguments.getSourceArgs()); listeners.environmentPrepared(environment); return environment; }
- 创建上下文,根据应用类型创建合适的应用上下文。
protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { contextClass = Class.forName(this.webApplicationType.getApplicationContextClassName()); } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Unable to create a default ApplicationContext, " + "please specify an ApplicationContextClass", ex); } } return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass); }
- 刷新上下文,初始化所有单例Bean,启动Spring生命周期。
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } }
- 通知监听器启动完成,执行
ApplicationRunner
和CommandLineRunner
。private void callRunners(ApplicationContext context, ApplicationArguments args) { List<Object> runners = new ArrayList<>(); runners.addAll(context.getBeansOfType(ApplicationRunner.class).values()); runners.addAll(context.getBeansOfType(CommandLineRunner.class).values()); AnnotationAwareOrderComparator.sort(runners); for (Object runner : new LinkedHashSet<>(runners)) { if (runner instanceof ApplicationRunner) { callRunner((ApplicationRunner) runner, args); } if (runner instanceof CommandLineRunner) { callRunner((CommandLineRunner) runner, args); } } }
其中核心方法为refresh()
刷新上下文方法。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 准备刷新上下文
prepareRefresh();
// 2. 获取BeanFactory并进行初始化
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 为BeanFactory配置上下文相关信息
prepareBeanFactory(beanFactory);
try {
// 4. 子类覆盖方法,做进一步的BeanFactory初始化
postProcessBeanFactory(beanFactory);
// 5. 调用BeanFactoryPostProcessors
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册BeanPostProcessors
registerBeanPostProcessors(beanFactory);
// 7. 初始化消息源(用于国际化)
initMessageSource();
// 8. 初始化事件广播器
initApplicationEventMulticaster();
// 9. 子类覆盖方法,在上下文刷新的时候进行进一步的处理
onRefresh();
// 10. 注册监听器以便监听事件
registerListeners();
// 11. 初始化所有单例Bean
finishBeanFactoryInitialization(beanFactory);
// 12. 完成刷新过程,通知生命周期处理器
finishRefresh();
}
catch (BeansException ex) {
// 如果在刷新过程中出现异常,则销毁已创建的单例Beans以避免资源泄漏
destroyBeans();
cancelRefresh(ex);
throw ex;
}
finally {
// 重置标志位
resetCommonCaches();
}
}
}
prepareRefresh
准备刷新容器,此方法做一些刷新容器的准备工作:- 设置开启时间和对应标志位。
- 获取环境对象。
- 设置监听器和一些时间的集合对象。
obtainFreshBeanFactory
创建容器对象:DefaultListableBeanFactory
;加载xml配置文件属性值到工厂中,最重要的是BeanDefinition
。prepareBeanFactory
完成Bean工厂的某些初始化操作:- 设置
BeanDefinition
的类加载器。 - 设置Spring容器默认的类型转换器。
- 设置Spring解析EL表达式的解析器。
- 添加一个Bean的后置处理器
ApplicationContextAwareProcessor
。 - 将Bean工厂的一些类,比如
ApplicationContext
直接注册到单例池中。 - 去除一些在
byType
或者byName
的时候需要过滤掉的一些Bean(Spring在依赖注入的时候会先在这些默认注册的Bean中进行byType找,如果找到了,就加入到列表中,简单来说就是比如你在Bean中依赖注入了ApplicationContext
,那么Spring会把默认注册的这些Bean中找到然后进行注册)。 - 将系统的环境信息、Spring容器的启动环境信息、操作系统的环境信息直接注册成一个单例的Bean。
- 设置
postProcessBeanFactory
这里是一个空壳方法,Spring目前还没有对他进行实现;这个方法是留给子类进行实现的,后续可以添加一些用户自定义的或者默认的一些特殊的后置处理器工程到beanFactory
中去。invokeBeanFactoryPostProcessors
调用后置处理器;将系统中所有符合条件的普通类都扫描成了一个BeanDefinition
并且放入到了beanDefinitionMap
中,包括业务的Bean,Bean的后置处理器、Bean工厂的后置处理器等。- 将标记为容器单例类扫描成
BeanDefinition
放入BeanDefinitionMap
。 - 处理
@Import
注解。 - 如果我们的配置类是
@Configuration
的,那么会生成这个配置类的CGLIB代理类,如果没有加@Configuration
,则就是一个普通Bean。
- 将标记为容器单例类扫描成
registerBeanPostProcessors
从beanDefinitionMap
中取出Bean的后置处理器然后放入到后置处理器的缓存列表中。initMessageSource
初始化国际化资源信息。initApplicationEventMulticaster
事件注册器初始化。onRefresh
空壳方法,留给子类实现。registerListeners
将容器中和BeanDefinitionMap
中的监听器添加到事件监听器中。finishBeanFactoryInitialization
创建单例池,将容器中非懒加载的Bean,单例Bean创建对象放入单例池中,包括容器的依赖注入。finishRefresh
容器启动过后,发布事件。