run方法分析
//run方法内容 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); } }
run 方法创建和刷新应用ApplicationContext,内容很多,分了几个子方法执行不一样的操作。
1、StopWatch stopWatch = new StopWatch();
StopWatch 是一个spring util 包下的工具类,是一个计时器,能计算代码段耗时时间。StopWatch使用操作参考:https://www.cnblogs.com/xiaotongye/p/12745027.html
run方法中在最开始创建StopWatch并start开始计算。在所有的操作完成后调用stop方法结束计时,然后通过log info输出格式化后的时间。
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); // do something stopWatch.stop();
if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); //输出计时时间 } }
2、configureHeadlessProperty()
private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless"; private void configureHeadlessProperty() { System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, System.getProperty( SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless))); }
configureHeadlessProperty 方法用于配置应用为headless模式、headless模式可以在没有检测到显示器、鼠标等外设情况下,依然能启动应用程序。通过System.setProperty方法设置成一个系统属性,名为"java.awt.headless"。
3、SpringApplicationRunListeners listeners = getRunListeners(args);
spring.factories 文件中定义了一个SpringApplicationRunListener # Run Listeners org.springframework.boot.SpringApplicationRunListener=\ org.springframework.boot.context.event.EventPublishingRunListener
-------------------------------------------------------------------------
public ConfigurableApplicationContext run(String... args) { // 获取listeners SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); //-----创建和刷新应用上下文内容操作--------------------------------- context = createApplicationContext(); analyzers = new FailureAnalyzers(context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); ---------------------------------------------------------- listeners.finished(context, null); return context; } private SpringApplicationRunListeners getRunListeners(String[] args) { Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class }; return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances( SpringApplicationRunListener.class, types, this, args)); }
getRunListeners方法同样使用getSpringFactoriesInstances方法,从spring.factories资源文件中得到要创建的SpringApplicationRunListener进行初始化,并把创建的Listener加入到集合中,然后赋值到SpringApplicationRunListeners类的List<SpringApplicationRunListener> listeners 集合中。listeners 在创建和刷新应用上下文前后分别执行了start方法和finished方法,并且在创建和刷新上下文的过程方法将listeners作为参数传入,在该过程中继续调用listener是类中的方法。这里可以看出SpringAlipplicaitonRunListeners在run方法中的不同阶段去执行一系列操作。在springboot spring.factories中只定义了EventPublishingRunListener一个listener。从名字上看这是一个事件发布监听器。进入EventPublishingRunListener类看看有什么内容
org.springframework.boot.context.event.EventPublishingRunListenesr类代码内容:
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered { private final SpringApplication application; private final String[] args; private final SimpleApplicationEventMulticaster initialMulticaster; 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); } } @Override public int getOrder() { return 0; } @Override @SuppressWarnings("deprecation") public void starting() { this.initialMulticaster .multicastEvent(new ApplicationStartedEvent(this.application, this.args)); } @Override public void environmentPrepared(ConfigurableEnvironment environment) { this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent( this.application, this.args, environment)); } @Override public void contextPrepared(ConfigurableApplicationContext context) { } @Override public void contextLoaded(ConfigurableApplicationContext context) { for (ApplicationListener<?> listener : this.application.getListeners()) { if (listener instanceof ApplicationContextAware) { ((ApplicationContextAware) listener).setApplicationContext(context); } context.addApplicationListener(listener); } this.initialMulticaster.multicastEvent( new ApplicationPreparedEvent(this.application, this.args, context)); } @Override public void finished(ConfigurableApplicationContext context, Throwable exception) { SpringApplicationEvent event = getFinishedEvent(context, exception); if (context != null) { // Listeners have been registered to the application context so we should // use it at this point if we can context.publishEvent(event); } else { if (event instanceof ApplicationFailedEvent) { this.initialMulticaster.setErrorHandler(new LoggingErrorHandler()); } this.initialMulticaster.multicastEvent(event); } } private SpringApplicationEvent getFinishedEvent( ConfigurableApplicationContext context, Throwable exception) { if (exception != null) { return new ApplicationFailedEvent(this.application, this.args, context, exception); } return new ApplicationReadyEvent(this.application, this.args, context); } private static class LoggingErrorHandler implements ErrorHandler { private static Log logger = LogFactory.getLog(EventPublishingRunListener.class); @Override public void handleError(Throwable throwable) { logger.warn("Error calling ApplicationEventListener", throwable); } } }
EventPublishingRunListener 主要方法解析:
EventPublishingRunListener 初始化操作:赋值args、和application、创建事件广播器以及将application对象中各个监听器listener加入到广播器的集合中。
EventPublishingRunListener starting方法:广播一个ApplicationStartedEvent 事件( 在首次启动run方法时立即调用。 可用于非常早的初始化。)
EventPublishingRunListener environmentPrepared方法:广播一个ApplicationEnvironmentPreparedEvent事件(在环境准备好之后但在ApplicationContext创建之前调用)
EventPublishingRunListener contextPrepared方法:空方法
EventPublishingRunListener contextLoaded方法:广播一个ApplicationPreparedEvent事件(在ApplicationContext已经创建好,但是未进行refresh之前调用)
EventPublishingRunListener finished方法:根据exception是否为空,空则广播一个ApplicationFailedEvent事件,反之广播一个ApplicationReadyEvent事件(在run方法完成之前调用)
在run方法中,按照代码执行顺序getRunListeners(args)代码后就是调用listeners.starting() 方法,这里starting方法就是发布了一个ApplicationStartedEvent 事件。
start方法调用SimpleApplicationEventMulticaster 的multicastEvent 广播事件,参数为广播的事件类型。multicastEvent 方法用到了线程池Executor ,分别用线程执行invokeListener方法,调用监听器的监听事件onApplicationEvent执
行监听后处理。
public void starting() { this.initialMulticaster .multicastEvent(new ApplicationStartedEvent(this.application, this.args)); } public void multicastEvent(ApplicationEvent event) { multicastEvent(event, resolveDefaultEventType(event)); } 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); } } } protected void invokeListener(ApplicationListener listener, ApplicationEvent event) { ErrorHandler errorHandler = getErrorHandler(); if (errorHandler != null) { try { listener.onApplicationEvent(event); } catch (Throwable err) { errorHandler.handleError(err); } } else { try { listener.onApplicationEvent(event); } catch (ClassCastException ex) { String msg = ex.getMessage(); if (msg == null || msg.startsWith(event.getClass().getName())) { // Possibly a lambda-defined listener which we could not resolve the generic event type for Log logger = LogFactory.getLog(getClass()); if (logger.isDebugEnabled()) { logger.debug("Non-matching event type for listener: " + listener, ex); } } else { throw ex; } } } }
spring.factories 配置文件中定义的监听器
# 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
Listeners.starting()方法执行完后,这些监听器分别响应了对应的事件操作。比如在LoggingApplicationListener 监听器ApplicationStartingEvent事件处理中,对日志系统进行初始化前加载操作;
LoggingApplicationListener 类中的onAPPlicationStartingEvent方法
private void onApplicationStartingEvent(ApplicationStartingEvent event) { this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader()); //获取日志系统 this.loggingSystem.beforeInitialize();//初始化前操作 }
到此,run方法中的listener执行完成,接着是进行创建和刷新ApplicationContext内容。。。。。。
=================================================================================================================================