spring boot 2.0 源码分析(二)

 在上一章学习了spring boot 2.0启动的大概流程以后,今天我们来深挖一下SpringApplication实例变量的run函数。

先把这段run函数的代码贴出来:

    /**      * Run the Spring application, creating and refreshing a new      * {@link ApplicationContext}.      * @param args the application arguments (usually passed from a Java main method)      * @return a running {@link ApplicationContext}      */     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 = createApplicationContext();             exceptionReporters = getSpringFactoriesInstances(                     SpringBootExceptionReporter.class,                     new Class[] { ConfigurableApplicationContext.class }, context);             prepareContext(context, environment, listeners, applicationArguments,                     printedBanner);             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;     }

我们先来分析其中的第一个关键代码:SpringApplicationRunListeners listeners = getRunListeners(args);
这行代码是获取监听器,我们先跳转到getRunListeners中看一下:

    private SpringApplicationRunListeners getRunListeners(String[] args) {         Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };         return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(                 SpringApplicationRunListener.class, types, this, args));     }

在这段代码中,我们看到获取监听器,是new出来了一个SpringApplicationRunListeners实例并返回。
再次跳转到SpringApplicationRunListeners的构造函数中,看到一下发生了什么:

    SpringApplicationRunListeners(Log log,      Collection<? extends SpringApplicationRunListener> listeners) {         this.log = log;         this.listeners = new ArrayList(listeners);     }

在这个构造函数里,我们看到其只是把接收到的listeners参数,保存到实例变量里,没有过多的操作。
所以,重点是在listeners参数这里,而listeners是通过getSpringFactoriesInstances创建出来的,来看一下getSpringFactoriesInstances函数做了什么事情吧:

    private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,             Class<?>[] parameterTypes, Object... args) {         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();         // Use names and ensure unique to protect against duplicates         Set<String> names = 
                        
关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信