springboot情操陶冶-SpringApplication(二)

 承接前文springboot情操陶冶-SpringApplication(一),本文将对run()方法作下详细的解析

SpringApplication#run()

main函数经常调用的run()方法是我们分析的关键,先上源码

    public ConfigurableApplicationContext run(String... args) {         StopWatch stopWatch = new StopWatch();         stopWatch.start();         ConfigurableApplicationContext context = null;         Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();         // 读取java.awt.headless系统变量,默认为true.常用于linux图片的渲染         configureHeadlessProperty();         // 获取SpringApplicationRunListener接口集合并实例化调用公共接口starting()         SpringApplicationRunListeners listeners = getRunListeners(args);         listeners.starting();         try {             ApplicationArguments applicationArguments = new DefaultApplicationArguments(                     args);             // environment configuration             ConfigurableEnvironment environment = prepareEnvironment(listeners,                     applicationArguments);             // spring.beaninfo.ignore属性读取             configureIgnoreBeanInfo(environment);             // springboot的banner样图             Banner printedBanner = printBanner(environment);             // 创建spring应用上下文(尚未刷新)             context = createApplicationContext();             // SpringBootExceptionReporter接口集合读取             exceptionReporters = getSpringFactoriesInstances(                     SpringBootExceptionReporter.class,                     new Class[] { ConfigurableApplicationContext.class }, context);             // applicationContext configuration             prepareContext(context, environment, listeners, applicationArguments,                     printedBanner);             // 刷新spring应用上下文             refreshContext(context);             afterRefresh(context, applicationArguments);             stopWatch.stop();             if (this.logStartupInfo) {                 new StartupInfoLogger(this.mainApplicationClass)                         .logStarted(getApplicationLog(), stopWatch);             }             // SpringApplicationRunListener接口的started()方法调用             listeners.started(context);             callRunners(context, applicationArguments);         }         catch (Throwable ex) {             handleRunFailure(context, ex, exceptionReporters, listeners);             throw new IllegalStateException(ex);         }          try {             // SpringApplicationRunListener接口的running()方法调用             listeners.running(context);         }         catch (Throwable ex) {             handleRunFailure(context, ex, exceptionReporters, null);             throw new IllegalStateException(ex);         }         return context;     }

以上的代码注释有点多,笔者分块来进行罗列分析

SpringApplication#getRunListeners()

获取SpringApplicationRunListener接口集合并实例化,根据前文得知,读取的是META\spring.factories文件中的对应属性,
此处笔者以org.springframework.boot.context.event.EventPublishingRunListener为例。


先观察下其构造函数

    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);         }     }

注意application.getListeners()方法,根据前文得知,其会拿到类型为ApplicationListener的集合并存入至SimpleApplicationEventMulticaster广播类中;
其余方法,比如starting()/started()/environmentPrepared()等等方法均是由其统一调用所有的ApplicationListener接口的对应事件。笔者此处以starting()为例

    @Override     public void starting() {         this.initialMulticaster.multicastEvent(                 new ApplicationStartingEvent(this.application, this.args));     }

其会找寻支持响应ApplicationStartingEvent事件的Listeners,并执行相应的事件方法。响应的监听器有LoggingApplicationListenerLiquibaseServiceLocatorApplicationListener

SpringApplication#prepareEnvironment()

关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信