[toc]
Application实例化
Spring Boot的启动始于:
1
| SpringApplication.run(DemoApplication.class, args);
|
相应实现:
1 2 3
| public static ConfigurableApplicationContext run(Object source, String... args) { return run(new Object[] { source }, args); }
|
1 2 3
| public static ConfigurableApplicationContext run(Object[] sources, String[] args) { return new SpringApplication(sources).run(args); }
|
它实际上会构造一个SpringApplication的实例,然后运行它的run方法:
1 2 3
| public SpringApplication(Object... sources) { initialize(sources); }
|
1 2 3 4 5 6 7 8 9 10
| private void initialize(Object[] sources) { if (sources != null && sources.length > 0) { this.sources.addAll(Arrays.asList(sources)); } this.webEnvironment = deduceWebEnvironment(); setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); }
|
deduceWebEnvironment()是推断应用类型是Standard还是Web,方法是在当类路径中找是否存在”javax.servlet.Servlet”,”org.springframework.web.context.ConfigurableWebApplicationContext”的类来判断的。
然后设置初始化器,会从类路径的META-INF/spring.factories处读取相应配置文件,读取配置文件中Key为:org.springframework.context.ApplicationContextInitializer的value。以spring-boot这个包为例,它的META-INF/spring.factories部分定义如下所示:
1 2 3 4 5 6
| # Application Context Initializers org.springframework.context.ApplicationContextInitializer=\ org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\ org.springframework.boot.context.ContextIdApplicationContextInitializer,\ org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\ org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer
|
因此这几个类名会实例化出来放在SpringApplication 的initializers中。
之后设置监听器,同上读取配置文件中Key为:org.springframework.context. ApplicationListener的value,然后加载实例化后,设置在listeners中。
1 2 3 4 5 6 7 8 9 10 11
| # Application Listeners org.springframework.context.ApplicationListener=\ org.springframework.boot.ClearCachesApplicationListener,\ org.springframework.boot.builder.ParentContextCloserApplicationListener,\ org.springframework.boot.context.FileEncodingApplicationListener,\ org.springframework.boot.context.config.AnsiOutputApplicationListener,\ org.springframework.boot.context.config.ConfigFileApplicationListener,\ org.springframework.boot.context.config.DelegatingApplicationListener,\ org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener,\ org.springframework.boot.logging.ClasspathLoggingApplicationListener,\ org.springframework.boot.logging.LoggingApplicationListener
|
spring boot支持的事件监听类型有如下四种:ApplicationStartedEvent、ApplicationEnvironmentPreparedEvent、ApplicationPreparedEvent、ApplicationFailedEvent。
然后设置mainApplicationClass:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| private Class<?> deduceMainApplicationClass() { try { StackTraceElement[] stackTrace = new RuntimeException().getStackTrace(); for (StackTraceElement stackTraceElement : stackTrace) { if ("main".equals(stackTraceElement.getMethodName())) { return Class.forName(stackTraceElement.getClassName()); } } } catch (ClassNotFoundException ex) { } return null; }
|
它通过构造一个运行时异常,通过异常栈中方法名为main的栈帧来得到入口类的名字。至此,对于SpringApplication实例的初始化过程就结束了。
Application#run()
完成了实例化,下面开始调用run方法。流程图如下:

源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start();
ConfigurableApplicationContext context = null; FailureAnalyzers analyzers = null; configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
Banner printedBanner = printBanner(environment);
context = createApplicationContext(); analyzers = new FailureAnalyzers(context);
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments); listeners.finished(context, null); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } }
|
第23行createApplicationContext()即创建Spring的主要组件ApplicationContext,对于Web应用,上ApplicationContext就是AnnotationConfigEmbeddedWebApplicationContext。
第30行refreshContext(context)即刷新ApplicationContext:
1 2 3 4 5 6 7 8 9 10 11
| private void refreshContext(ConfigurableApplicationContext context) { refresh(context); if (this.registerShutdownHook) { try { context.registerShutdownHook(); } catch (AccessControlException ex) { } } }
|
最终会调用到我们熟知的AbstractApplicationContext的refresh()方法。
第33行上下文后置处理afterRefresh()方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) { callRunners(context, args); }
private void callRunners(ApplicationContext context, ApplicationArguments args) { List<Object> runners = new ArrayList<Object>(); runners.addAll(context.getBeansOfType(ApplicationRunner.class).values()); runners.addAll(context.getBeansOfType(CommandLineRunner.class).values()); AnnotationAwareOrderComparator.sort(runners); for (Object runner : new LinkedHashSet<Object>(runners)) { if (runner instanceof ApplicationRunner) { callRunner((ApplicationRunner) runner, args); } if (runner instanceof CommandLineRunner) { callRunner((CommandLineRunner) runner, args); } } }
|
所谓的后置操作,就是在容器完成刷新后,依次调用注册的Runners。Runners可以是两个接口的实现类:org.springframework.boot.ApplicationRunner与org.springframework.boot.CommandLineRunner。
监听器Listener
再来看监听器是如何工作的呢?还是看上面ConfigurableApplicationContext#run()方法中第11行getRunListeners(),该方法源码如下:
1 2 3 4 5
| private SpringApplicationRunListeners getRunListeners(String[] args) { Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class }; return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances( SpringApplicationRunListener.class, types, this, args)); }
|
这里的getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),会在META-INF/spring.factories中找到:
1 2 3
| # Run Listeners org.springframework.boot.SpringApplicationRunListener=\ org.springframework.boot.context.event.EventPublishingRunListener
|
getSpringFactoriesInstances()返回了EventPublishingRunListener实例。EventPublishingRunListener的构造方法如下:
1 2 3 4 5 6 7 8
| public EventPublishingRunListener(SpringApplication application, String[] args) { this.application = application; this.args = args; this.initialMulticaster = new SimpleApplicationEventMulticaster(); for (ApplicationListener<?> listener : application.getListeners()) { this.initialMulticaster.addApplicationListener(listener); } }
|
构造方法中将SpringApplication中的监听器添加到了SimpleApplicationEventMulticaster的实例multicaster中。
接下来ConfigurableApplicationContext.run()方法中调用listeners.starting()方法,来看下:
1 2 3 4 5
| public void starting() { for (SpringApplicationRunListener listener : this.listeners) { listener.starting(); } }
|
1 2 3 4 5 6
| @Override @SuppressWarnings("deprecation") public void starting() { this.initialMulticaster .multicastEvent(new ApplicationStartedEvent(this.application, this.args)); }
|
在EventPublishingRunListener.starting()方法中,先创建一个ApplicationStartedEvent事件,将this.application传递进去,因此使用ApplicationStartedEvent监听器时可以获取SpringApplication实例。
SimpleApplicationEventMulticaster.multicastEvent():
1 2 3 4
| @Override public void multicastEvent(ApplicationEvent event) { multicastEvent(event, resolveDefaultEventType(event)); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Override public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @Override public void run() { invokeListener(listener, event); } }); } else { invokeListener(listener, event); } } }
|
getApplicationListeners()获取对应ApplicationEvent的listener,获取完指定事件对应监听器后,通过Executor执行一个子线程执行invokeListener(listener, event),该函数会调用监听器listener.onApplicationEvent(event)方法。
在SpringApplication.run()方法执行中,依次调用了listeners.starting()、listeners.environmentPrepared(environment)、listeners.contextLoaded(context)分别对应了ApplicationStartedEvent、ApplicationEnvironmentPreparedEvent、ApplicationPreparedEvent事件。
自定义启动扩展
基于上面的了解,我们就可以在Spring Boot启动添加自定义的初始化器、监听器等。
添加定制化的初始化器:
1 2 3 4 5 6 7 8 9 10 11
| public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.addInitializers(new CustomApplicationContextInitializer());
app.run(args); }
|
1 2 3 4 5 6 7 8
| public class CustomApplicationContextInitializer implements ApplicationContextInitializer { private static final Logger LOGGER = LoggerFactory.getLogger(CustomApplicationContextInitializer.class);
@Override public void initialize(ConfigurableApplicationContext applicationContext) { LOGGER.info("自定义的初始化器的initialize方法被执行了"); } }
|

添加定制化的监听器:
1
| app.addListeners(new CustomApplicationListener());
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class CustomApplicationListener implements ApplicationListener { private static final Logger LOGGER = LoggerFactory.getLogger(CustomApplicationListener.class);
public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ApplicationStartedEvent) { logInfo("ApplicationStartedEvent listened"); }
else if (event instanceof ApplicationEnvironmentPreparedEvent) { logInfo("ApplicationEnvironmentPreparedEvent listened"); }
else if (event instanceof ApplicationPreparedEvent) { logInfo("ApplicationPreparedEvent listened"); }
else if (event instanceof ApplicationReadyEvent) { logInfo("ApplicationReadyEvent listened"); }
else if (event instanceof ApplicationFailedEvent) { logInfo("ApplicationFailedEvent listened"); } }
private void logInfo(String log) { if (LOGGER.isInfoEnabled()) { LOGGER.info(log); } } }
|

添加定制化的后置Runners:
1 2 3 4 5 6 7 8 9 10 11 12
| @Component @Order(2) public class CustomApplicationRunner implements ApplicationRunner { private static final Logger LOGGER = LoggerFactory.getLogger(CustomApplicationRunner.class);
@Override public void run(ApplicationArguments arg) { if (LOGGER.isInfoEnabled()) { LOGGER.info("自定义ApplicationRunner运行了"); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| @Component @Order(1) public class CustomCommandLineRunner implements CommandLineRunner { private static final Logger LOGGER = LoggerFactory.getLogger(CustomCommandLineRunner.class);
@Override public void run(String... strings) throws Exception { if (LOGGER.isInfoEnabled()) { LOGGER.info("自定义CommandLineRunner运行了"); } } }
|
自定义Runner的添加方式和上述的初始化器以及监听器有点不同,就是Runners直接通过@Component注解添加即可,借助于包扫描机制,它们会被注册到容器中。至于它们运行的顺序,则可以通过上述的@Order注解来完成标注,数值越小的Runner优先级越高,因为源码中有AnnotationAwareOrderComparator.sort(runners),因此上面代码中,CustomCommandLineRunner将先于CustomApplicationRunner被执行。
启动打印Banner:
扩展的方式也很简单,看源代码就清楚该怎么扩展了:
1 2 3 4 5 6 7 8 9 10 11 12 13
| private Banner printBanner(ConfigurableEnvironment environment) { if (this.bannerMode == Banner.Mode.OFF) { return null; } ResourceLoader resourceLoader = this.resourceLoader != null ? this.resourceLoader : new DefaultResourceLoader(getClassLoader()); SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter( resourceLoader, this.banner); if (this.bannerMode == Mode.LOG) { return bannerPrinter.print(environment, this.mainApplicationClass, logger); } return bannerPrinter.print(environment, this.mainApplicationClass, System.out); }
|

转载自:
http://blog.csdn.net/dm_vincent/article/details/76735888
http://blog.csdn.net/dm_vincent/article/details/77151122