springboot 的启动入口是 SpringApplication run方法,代码如下:
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); Banner printedBanner = printBanner(environment); //此处创建 context context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); //初始化context 的核心逻辑都在这行代码里。 refreshContext(context); afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } listeners.started(context); callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } return context; }再具体分析下 refreshContext的代码逻辑
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. //清除缓存,并读取配置文件里的环境变量 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. // 此处的 bean factory 是通过父类GenericApplicationContext 初始化的 DefaultListableBeanFactory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. // 配置 beanFactory, 包括注册(第一次) BeanPostProcessor, 设置 classLoader等等。 // BeanPostProcessor 有两个主要的方法:postProcessBeforeInitialization 和 postProcessAfterInitialization 。 // 这个两个方法分别的执行时期是 bean 初始化之前和初始化之后。具体的执行时期后面会说到 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. //为 applicationContext的子类注册(第二次)个性化的 BeanPostProcessor postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. //执行 context 中注册的 BeanFactoryPostProcessor中的postProcessBeanFactory() 方法,BeanFactoryPostProcessor只有这一个方法 //BeanFactoryPostProcessor 是 bean 属性处理容器。即管理 bean工厂中的BeanDefinition, // BeanDefinition在 spring mvc 中就是 xml 文件中对应的 bean 标签(注意,是标签,而不是真实的 JAVA BEAN)。 //可以看到,此处已经 invoke 了postProcessBeanFactory() 方法。 而 BeanPostProcessor 的方法还没有被调用, //所以 BeanFactoryPostProcessor的执行是要早于BeanPostProcessor的。 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. //再次注册BeanPostProcessor(这已经是第三次注册, // 第一注册的是AbstractApplicationContext中用到的 processor, // 第二次为ServletWebServerApplicationContext 注册 processor)。 // 这次是为实际用到的 context注册 processor(spring boot 即是AnnotationConfigServletWebServerApplicationContext), // 并为根据优先级和 order 排序。 registerBeanPostProcessors(beanFactory); // Initialize message source for this context. // 实例化并注册 MessageSource类。MessageSource是国际化相关的接口 initMessageSource(); // Initialize event multicaster for this context. //初始化spring 事件广播器,ApplicationContext会通过广播器发送事件,负责监听广播器的 listener 会负责处理事件 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. // 在一些特殊的 ApplicationContext子类中实例化一些特殊的 bean. //例如ServletWebServerApplicationContext(AnnotationConfigServletWebServerApplicationContext的父类)会初始化TomcatWebServer, //并启动这个 server,在 spring boot 工程中,相当于启动了整个 spring boot 项目。 onRefresh(); // Check for listener beans and register them. //为ApplicationEventMulticaster注册监听 listener(ApplicationListener), //会有一些默认的 listener被注册。例如这是一个 dubbo provider的工程,就会注册DubboBannerApplicationListener // 同时也会有一些自定义的 listener. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //终于到了初始 java bean 的阶段, 注意此处只初始化单例的 bean, 并且非懒加载的类(默认即非懒加载)。 //虽然此时 java bean已经实例化,但是其依赖自动注入的 bean却不再此时注入,而是等到用到的时候再去获取, //所以这里不会出现循环依赖的问题。 // 一个 spring bean 的初始化过程如下: // 1. 执行构造器 // 2. BeanPostProcessor的postProcessBeforeInitialization方法 // 3. InitializingBean的afterPropertiesSet方法 // 4,@Bean注解的initMethod方法 // 5,BeanPostProcessor的postProcessAfterInitialization方法 // 6,DisposableBean的destroy方法 // 7,@Bean注解的destroyMethod方法 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. //实例化LifecycleProcessor并执行其 onRefresh()方法,刷新上下文,启动一些需要在初始化阶段启动的类(实现了Lifecycle接口的类) // 发布ContextRefreshedEvent事件,这个应该是表示上下文启动完成的事件 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... //清理单例 bean 的元数据缓存。 resetCommonCaches(); } } }至此, spring boot的启动过程就完成了, 基于篇幅和时间问题。其中还有很多代码细节没有仔细分析,这些就留给未来吧。
整个过程分析下来发现这个启动过程会有几个核心接口(应该也是 spring 整个 ioc机制的核心接口)
BeanFactory ApplicationContext BeanPostProcessor BeanFactoryPostProcessor ApplicationEventMulticaster BeanDefinition LifecycleProcessor 以及每个接口里面的方法及其执行时序。 弄清楚每一个接口的原理和具体使用场景,对我们使用和理解 spring 至关重要。