Spring源码的入口大家都知道,是run,但是点进去之后发现里面方法弯弯绕绕,不知道是遵循什么样的规则或者设计思路去实现的。 其实在Spring里有一个类已经写清楚了run的关键节点,就是 SpringApplicationRunListener 类。 下载源码,进去看他的方法注释,就可以看到它把整个run方法的周期都罗列清楚了
public interface SpringApplicationRunListener {
// 1 当run第一次启动时立即调用,非常早期的初始化
void starting(ConfigurableBootstrapContext bootstrapContext) ;
// 2 在ConfigurableEnvironment准备好之后,ApplicationContext创建好之前调用
void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
ConfigurableEnvironment environment) ;
// 3 在ApplicationContext创建好之后调用,但是资源还没开始加载
void contextPrepared(ConfigurableApplicationContext context);
// 4 在 application context加载完但是还没**刷新**的时候用
void contextLoaded(ConfigurableApplicationContext context);
// 5 application context已经**刷新**了但是CommandLineRunners和ApplicationRunners 还没调用
void started(ConfigurableApplicationContext context);
// 6 所有CommandLineRunners和ApplicationRunners都调用了(都run了)
void running(ConfigurableApplicationContext context);
// 7 在ApplicationContext发生故障时调用,如果发生时ApplicationContext还没准备好,就是null
void failed(ConfigurableApplicationContext context, Throwable exception);
}
有了这个思路之后,再回过头去看run的源码,会发现思路非常清晰
讲一下监听器里的几个重点对象
引导上下文:ConfigurableBootstrapContext ,是在准备应用上下文之前的引导上下文(参考计算机启动时的boot的定义),在准备应用上下文阶段会被释放掉
环境:ConfigurableEnvironment 主要是配置。这里如果点进去看,会发现他对于环境操作有很多关于优先级的处理。如果是做基础设施的工作,这里可能有用。
应用上下文:ConfigurableApplicationContext ,就是我们实际用来获取bean,最长使用的那个上下文,在web应用里,他的实现类一般是
AnnotationConfigServletWebServerApplicationContext
这里类上有个比较重要的注释
后面的bean会覆盖先加载的bean