SpringBoot启动过程学习

Springboot2.0.3 release.jar
spring.factories
////////////////////////////////////////////////////////////////////////////////////////////
# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader

# Run Listeners----->第一个启动的Listener
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers

# 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.web.context.ServerPortInfoApplicationContextInitializer

# 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.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor

# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer

# FailureAnalysisReporters
org.springframework.boot.diagnostics.FailureAnalysisReporter=\
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter

 

执行顺序

1.listener.starting
2.listener.environmentPrepared
    >>触发BootstrapApplicationListener,调用onApplicationEvent,
      然后创建SpringApplicationBuilder builder = new SpringApplicationBuilder(), 又回到SpringApplication.run.
      然后1,2(中间短路),3,4,5执行一遍.
3.listener.contextPrepared
    >>context.refresh
4.listener.started
5.listener.running

 

山穷水尽的时候, 发现别人启动的一个报错, 终于摸清楚了调用栈.

从这个对战里可以看出来.SpringApplication.prepareEnvironment 这一步一直走,触发事件, 然后BootstrapApplicationListener捕捉到事件然后开始SpringApplicationBuilder.run

https://github.com/spring-cloud/spring-cloud-config/issues/836

java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApplicationBuilder.([Ljava/lang/Object;)V
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.bootstrapServiceContext(BootstrapApplicationListener.java:120)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:84)
at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:62)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:167)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:122)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:72)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:54)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:360)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:328)

 

关于事件的一个一些知识:

https://www.logicbig.com/tutorials/spring-framework/spring-boot/application-listener.html

 

springboot启动的若干种方式, 其实吧, 平常启动的时候就包含了两种方式.

http://www.51gjie.com/javaweb/1042.html

@SpringBootApplication 
public class Application {
    //方式一
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    //方式二
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(MySpringConfiguration.class);
        app.run(args);
    }
    //方式三
    public static void main(String[] args) {
        new SpringApplicationBuilder()
            .sources(Parent.class)
            .child(Application.class)
            .run(args);
    }
}

 

代码笔记:

  1 SpringApplication.run(XxxApplication.class, args);
  2 ->return run(new Class<?>[] { primarySource }, args);
  3   ->return new SpringApplication(primarySources).run(args);
  4     ->this(null, primarySources);
  5                 //##############################################################
  6                 public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
  7                     this.resourceLoader = resourceLoader;
  8                     Assert.notNull(primarySources, "PrimarySources must not be null");
  9                     this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
 10                     this.webApplicationType = deduceWebApplicationType();
 11                             //这一段比较费解,做了大量的class load, 还有异常个抛出, 结果其实返回一个 SERVLET
 12                             //isPresent方法的核心机制就是通过反射创建指定的类,根据在创建过程中是否抛出异常来判断该类是否存在。
 13                             //##############################################################            
 14                             private WebApplicationType deduceWebApplicationType() {
 15                                 //当DispatcherHandler存在,并且DispatcherServlet和ServletContainer都不存在,则返回类型为WebApplicationType.REACTIVE。
 16                                 if (ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS, null)
 17                                         && !ClassUtils.isPresent(MVC_WEB_ENVIRONMENT_CLASS, null)) {
 18                                     return WebApplicationType.REACTIVE;
 19                                 }
 20                                 //当SERVLET或ConfigurableWebApplicationContext任何一个不存在时,说明当前应用为非Web应用,返回WebApplicationType.NONE。
 21                                 //{ "javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext" }
 22                                 for (String className : WEB_ENVIRONMENT_CLASSES) {
 23                                     if (!ClassUtils.isPresent(className, null)) {
 24                                         return WebApplicationType.NONE;
 25                                     }
 26                                 }
 27                                 return WebApplicationType.SERVLET;
 28                             }
 29                             //##############################################################
 30                     //这一段, 就是load 类型是ApplicationContextInitializer.class 的所有类, 并创建实例
 31                     //"org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer",
 32                     //"org.springframework.boot.context.ContextIdApplicationContextInitializer",
 33                     //"org.springframework.boot.context.config.DelegatingApplicationContextInitializer",
 34                     //"org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer",
 35                     //"org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer",
 36                     //"org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener"
 37                     setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
 38                     
 39                     //"org.springframework.cloud.bootstrap.BootstrapApplicationListener",
 40                     //"org.springframework.cloud.bootstrap.LoggingSystemShutdownListener",
 41                     //"org.springframework.cloud.context.restart.RestartListener",
 42                     //"org.springframework.boot.ClearCachesApplicationListener",
 43                     //"org.springframework.boot.builder.ParentContextCloserApplicationListener",
 44                     //"org.springframework.boot.context.FileEncodingApplicationListener",
 45                     //"org.springframework.boot.context.config.AnsiOutputApplicationListener",
 46                     //"org.springframework.boot.context.config.ConfigFileApplicationListener",
 47                     //"org.springframework.boot.context.config.DelegatingApplicationListener",
 48                     //"org.springframework.boot.context.logging.ClasspathLoggingApplicationListener",
 49                     //"org.springframework.boot.context.logging.LoggingApplicationListener",
 50                     //"org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener",
 51                     //"org.springframework.boot.autoconfigure.BackgroundPreinitializer"
 52                     setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
 53                     
 54                     //这个需要这么费劲么...为什么要转了一圈才
 55                     this.mainApplicationClass = deduceMainApplicationClass();
 56                             //##############################################################
 57                             private Class<?> deduceMainApplicationClass() {
 58                                 try {
 59                                     StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
 60                                     for (StackTraceElement stackTraceElement : stackTrace) {
 61                                         if ("main".equals(stackTraceElement.getMethodName())) {
 62                                             return Class.forName(stackTraceElement.getClassName());
 63                                         }
 64                                     }
 65                                 }
 66                                 catch (ClassNotFoundException ex) {
 67                                     // Swallow and continue
 68                                 }
 69                                 return null;
 70                             }
 71                             //##############################################################
 72                     
 73                 }//SpringApplication-end
 74                 //##############################################################
 75                 
 76     ->public ConfigurableApplicationContext run(String... args) {
 77         
 78         StopWatch stopWatch = new StopWatch();
 79         stopWatch.start();
 80         
 81         ConfigurableApplicationContext context = null;
 82         Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
 83         
 84         configureHeadlessProperty();
 85                 //##############################################################
 86                 private void configureHeadlessProperty() {
 87                     System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
 88                 }
 89                 //##############################################################
 90         
 91         //前面在构造函数里load了好多个Listener, 而现在要获取RunListeners, 只有1个:org.springframework.boot.context.event.EventPublishingRunListener
 92         SpringApplicationRunListeners listeners = getRunListeners(args);
 93                 //##############################################################
 94                 private SpringApplicationRunListeners getRunListeners(String[] args) {
 95                     Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
 96                     return new SpringApplicationRunListeners(
 97                         logger, 
 98                         getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args)
 99                                 //##############################################################                
100                                 private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
101                                     ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
102                                     // Use names and ensure unique to protect against duplicates
103                                     Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
104                                             //##############################################################
105                                             public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
106                                                 String factoryClassName = factoryClass.getName();
107                                                 return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
108                                                         //##############################################################
109                                                         private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
110                                                             MultiValueMap<String, String> result = cache.get(classLoader);
111                                                             if (result != null) {
112                                                                 return result;
113                                                             }
114 
115                                                             try {
116                                                                 Enumeration<URL> urls = (classLoader != null ?
117                                                                         classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
118                                                                         ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
119                                                                 result = new LinkedMultiValueMap<>();
120                                                                 while (urls.hasMoreElements()) {
121                                                                     URL url = urls.nextElement();
122                                                                     UrlResource resource = new UrlResource(url);
123                                                                     Properties properties = PropertiesLoaderUtils.loadProperties(resource);
124                                                                     for (Map.Entry<?, ?> entry : properties.entrySet()) {
125                                                                         List<String> factoryClassNames = Arrays.asList(
126                                                                                 StringUtils.commaDelimitedListToStringArray((String) entry.getValue()));
127                                                                         result.addAll((String) entry.getKey(), factoryClassNames);
128                                                                     }
129                                                                 }
130                                                                 cache.put(classLoader, result);
131                                                                 return result;
132                                                             } catch (IOException ex) {
133                                                                 throw new IllegalArgumentException("Unable to load factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
134                                                             }
135                                                         }//loadSpringFactories-end
136                                                         //##############################################################
137                                                 }//loadFactoryNames-end
138                                                 //##############################################################
139                                     
140                                     List<T> instances = createSpringFactoriesInstances(type, parameterTypes,classLoader, args, names);
141                                                 //##############################################################                        
142                                                 private <T> List<T> createSpringFactoriesInstances(
143                                                                                                 Class<T> type,
144                                                                                                 Class<?>[] parameterTypes, 
145                                                                                                 ClassLoader classLoader, 
146                                                                                                 Object[] args,
147                                                                                                 Set<String> names
148                                                 ){
149                                                     List<T> instances = new ArrayList<>(names.size());
150                                                     for (String name : names) {
151                                                         try {
152                                                             Class<?> instanceClass = ClassUtils.forName(name, classLoader);
153                                                             Assert.isAssignable(type, instanceClass);
154                                                             Constructor<?> constructor = instanceClass
155                                                                     .getDeclaredConstructor(parameterTypes);
156                                                             T instance = (T) BeanUtils.instantiateClass(constructor, args);
157                                                             instances.add(instance);
158                                                         }
159                                                         catch (Throwable ex) {
160                                                             throw new IllegalArgumentException(
161                                                                     "Cannot instantiate " + type + " : " + name, ex);
162                                                         }
163                                                     }
164                                                     return instances;
165                                                 }//createSpringFactoriesInstances-end
166                                                 //##############################################################
167                                                                 
168                                     AnnotationAwareOrderComparator.sort(instances);
169                                     return instances;
170                                 }//getSpringFactoriesInstances-end
171                                 //##############################################################                
172                         
173                     );
174                 }//getRunListeners-end
175                 //##############################################################
176         
177         listeners.starting();
178                 //##############################################################
179                 public void starting() {
180                     for (SpringApplicationRunListener listener : this.listeners) {
181                         listener.starting();
182                     }
183                 }
184                 //##############################################################
185     
186         try {
187           //封装args,
188           ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
189           //environment, 类似properties的配置类
190           ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
191                       //##############################################################
192                     private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
193                         // Create and configure the environment
194                         ConfigurableEnvironment environment = getOrCreateEnvironment();
195                                 //##############################################################
196                                 private ConfigurableEnvironment getOrCreateEnvironment() {
197                                     if (this.environment != null) {
198                                         return this.environment;
199                                     }
200                                     if (this.webApplicationType == WebApplicationType.SERVLET) {
201                                         return new StandardServletEnvironment();
202                                     }
203                                     return new StandardEnvironment();
204                                 }
205                                 //##############################################################
206                         
207                         configureEnvironment(environment, applicationArguments.getSourceArgs());
208                                 //##############################################################
209                                 protected void configureEnvironment(ConfigurableEnvironment environment,
210                                     String[] args) {
211                                     configurePropertySources(environment, args);
212                                     configureProfiles(environment, args);
213                                 }
214                                 //##############################################################
215                         
216                         //这里,非常坑!!!---> 这里的listener 只有一个, 是EventPublishingRunListeners
217                         listeners.environmentPrepared(environment);
218                                 //##############################################################
219                                 public void environmentPrepared(ConfigurableEnvironment environment) {
220                                     for (SpringApplicationRunListener listener : this.listeners) {
221                                         listener.environmentPrepared(environment);
222                                                 //要注意这里:ApplicationEnvironmentPreparedEvent!!!!, 这个Event一旦广播就会进入另外一番天地
223                                                 //**********************************************************************************************
224                                                 @Override
225                                                 public void environmentPrepared(ConfigurableEnvironment environment) {
226                                                     this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(
227                                                             this.application, this.args, environment));
228                                                 }
229                                                 //**********************************************************************************************
230                                     }
231                                 }
232                                 //##############################################################
233                             
234                         bindToSpringApplication(environment);
235                                 //##############################################################
236                                 protected void bindToSpringApplication(ConfigurableEnvironment environment) {
237                                     try {
238                                         Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
239                                     }
240                                     catch (Exception ex) {
241                                         throw new IllegalStateException("Cannot bind to SpringApplication", ex);
242                                     }
243                                 }
244                                 //##############################################################
245                             
246                         if (this.webApplicationType == WebApplicationType.NONE) {
247                             environment = new EnvironmentConverter(getClassLoader()).convertToStandardEnvironmentIfNecessary(environment);
248                         }
249                         
250                         ConfigurationPropertySources.attach(environment);
251                                 //##############################################################
252                                 public static void attach(Environment environment) {
253                                     Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
254                                     MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
255                                     PropertySource<?> attached = sources.get(ATTACHED_PROPERTY_SOURCE_NAME);
256                                     if (attached != null && attached.getSource() != sources) {
257                                         sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
258                                         attached = null;
259                                     }
260                                     if (attached == null) {
261                                         sources.addFirst(new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,new SpringConfigurationPropertySources(sources)));
262                                     }
263                                 }
264                                 //##############################################################
265                         return environment;
266                     }//prepareEnvironment-end
267                     //##############################################################
268 
269           configureIgnoreBeanInfo(environment);
270                     //##############################################################
271                     private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
272                         if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
273                             Boolean ignore = environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);
274                             System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString());
275                         }
276                     }
277                     //##############################################################
278           
279           Banner printedBanner = printBanner(environment);
280                     //##############################################################
281                     private Banner printBanner(ConfigurableEnvironment environment) {
282                         if (this.bannerMode == Banner.Mode.OFF) {
283                             return null;
284                         }
285                         ResourceLoader resourceLoader = (this.resourceLoader != null ? this.resourceLoader
286                                 : new DefaultResourceLoader(getClassLoader()));
287                         SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(
288                                 resourceLoader, this.banner);
289                         if (this.bannerMode == Mode.LOG) {
290                             return bannerPrinter.print(environment, this.mainApplicationClass, logger);
291                         }
292                         return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
293                     }
294                     //##############################################################
295                 
296           context = createApplicationContext();
297                     //##############################################################
298                     /**
299                      * Strategy method used to create the {@link ApplicationContext}. By default this
300                      * method will respect any explicitly set application context or application context
301                      * class before falling back to a suitable default.
302                      * @return the application context (not yet refreshed)
303                      * @see #setApplicationContextClass(Class)
304                      */
305                     protected ConfigurableApplicationContext createApplicationContext() {
306                         Class<?> contextClass = this.applicationContextClass;
307                         if (contextClass == null) {
308                             try {
309                                 switch (this.webApplicationType) {
310                                 case SERVLET:
311                                     contextClass = Class.forName(DEFAULT_WEB_CONTEXT_CLASS);
312                                     break;
313                                 case REACTIVE:
314                                     contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
315                                     break;
316                                 default:
317                                     contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
318                                 }
319                             }
320                             catch (ClassNotFoundException ex) {
321                                 throw new IllegalStateException(
322                                         "Unable create a default ApplicationContext, "
323                                                 + "please specify an ApplicationContextClass",
324                                         ex);
325                             }
326                         }
327                         return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
328                     }
329                     //##############################################################
330         
331           exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);
332                     //##############################################################
333                     private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
334                             Class<?>[] parameterTypes, Object... args) {
335                         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
336                         // Use names and ensure unique to protect against duplicates
337                         Set<String> names = new LinkedHashSet<>(
338                                 SpringFactoriesLoader.loadFactoryNames(type, classLoader));
339                         List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
340                                 classLoader, args, names);
341                         AnnotationAwareOrderComparator.sort(instances);
342                         return instances;
343                     }
344                     //##############################################################
345           //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
346           //这一步非常重要!!!!!!!!!!!
347           //!!!!!!!!!!!!!!!!!!!!!!!!!    
348           prepareContext(context, environment, listeners, applicationArguments,printedBanner);
349                     //##############################################################
350                     private void prepareContext(ConfigurableApplicationContext context,
351                             ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
352                             ApplicationArguments applicationArguments, Banner printedBanner) {
353                         context.setEnvironment(environment);
354                         postProcessApplicationContext(context);
355                         
356                         //在这个里面,做了初始化, initializer 有顺序,DelegatingA...C...Init...是0,ContextIdA..C..Init...是2.....最大
357                         applyInitializers(context);
358                                 //##############################################################
359                                 protected void applyInitializers(ConfigurableApplicationContext context) {
360                                     for (ApplicationContextInitializer initializer : getInitializers()) {
361                                         Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(
362                                                 initializer.getClass(), ApplicationContextInitializer.class);
363                                         Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
364                                         initializer.initialize(context);
365                                     }
366                                 }
367                                 //##############################################################
368                         //第一次进来的时候, 这个listerners只有1个元素:EventPublishingRunListener    
369                         listeners.contextPrepared(context);
370                         if (this.logStartupInfo) {
371                             logStartupInfo(context.getParent() == null);
372                             logStartupProfileInfo(context);
373                         }
374 
375                         // Add boot specific singleton beans
376                         context.getBeanFactory().registerSingleton("springApplicationArguments",
377                                 applicationArguments);
378                         if (printedBanner != null) {
379                             context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
380                         }
381 
382                         // Load the sources
383                         Set<Object> sources = getAllSources();
384                         Assert.notEmpty(sources, "Sources must not be empty");
385                         load(context, sources.toArray(new Object[0]));
386                         listeners.contextLoaded(context);
387                     }
388                     //##############################################################
389                 
390           refreshContext(context);
391                     //##############################################################
392                     private void refreshContext(ConfigurableApplicationContext context) {
393                         refresh(context);
394                                 //##############################################################
395                                 /**
396                                  * Refresh the underlying {@link ApplicationContext}.
397                                  * @param applicationContext the application context to refresh
398                                  */
399                                 protected void refresh(ApplicationContext applicationContext) {
400                                     Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
401                                     ((AbstractApplicationContext) applicationContext).refresh();
402                                 }
403                                 //##############################################################
404                         
405                         if (this.registerShutdownHook) {
406                             try {
407                                 context.registerShutdownHook();
408                             }
409                             catch (AccessControlException ex) {
410                                 // Not allowed in some environments.
411                             }
412                         }
413                     }//refreshContext-end
414                     //##############################################################
415                     
416           afterRefresh(context, applicationArguments);
417                     //##############################################################
418                     /**
419                      * Called after the context has been refreshed.
420                      * @param context the application context
421                      * @param args the application arguments
422                      */
423                     protected void afterRefresh(ConfigurableApplicationContext context,
424                             ApplicationArguments args) {
425                     }
426                     //##############################################################
427           
428           stopWatch.stop();
429           
430           if (this.logStartupInfo) {
431               new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
432                     //##############################################################   
433                     public void logStarted(Log log, StopWatch stopWatch) {
434                         if (log.isInfoEnabled()) {
435                             log.info(getStartedMessage(stopWatch));
436                         }
437                     }
438                     private String getStartupMessage() {
439                         StringBuilder message = new StringBuilder();
440                         message.append("Starting ");
441                         message.append(getApplicationName());
442                         message.append(getVersion(this.sourceClass));
443                         message.append(getOn());
444                         message.append(getPid());
445                         message.append(getContext());
446                         return message.toString();
447                     }
448                     private StringBuilder getRunningMessage() {
449                         StringBuilder message = new StringBuilder();
450                         message.append("Running with Spring Boot");
451                         message.append(getVersion(getClass()));
452                         message.append(", Spring");
453                         message.append(getVersion(ApplicationContext.class));
454                         return message;
455                     }
456                     //##############################################################
457           }
458           
459           listeners.started(context);
460                     //##############################################################
461                     public void started(ConfigurableApplicationContext context) {
462                         for (SpringApplicationRunListener listener : this.listeners) {
463                             listener.started(context);
464                         }
465                     }
466                     //##############################################################
467                     
468           //第一次,runner是空    
469           callRunners(context, applicationArguments);
470                     //##############################################################
471                     private void callRunners(ApplicationContext context, ApplicationArguments args) {
472                         List<Object> runners = new ArrayList<>();
473                         runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
474                         runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
475                         AnnotationAwareOrderComparator.sort(runners);
476                         for (Object runner : new LinkedHashSet<>(runners)) {
477                             if (runner instanceof ApplicationRunner) {
478                                 callRunner((ApplicationRunner) runner, args);
479                                         //##############################################################
480                                         private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
481                                             try {
482                                                 (runner).run(args);
483                                             }
484                                             catch (Exception ex) {
485                                                 throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
486                                             }
487                                         }
488                                         //##############################################################
489                             }
490                             if (runner instanceof CommandLineRunner) {
491                                 callRunner((CommandLineRunner) runner, args);
492                                         //##############################################################
493                                         private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
494                                             try {
495                                                 (runner).run(args.getSourceArgs());
496                                             }
497                                             catch (Exception ex) {
498                                                 throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
499                                             }
500                                         }
501                                         //##############################################################
502                             }
503                         }
504                     }
505                     //##############################################################
506         }catch (Throwable ex) {
507           handleRunFailure(context, ex, exceptionReporters, listeners);
508                     //##############################################################      
509                     private void handleRunFailure(ConfigurableApplicationContext context,
510                             Throwable exception,
511                             Collection<SpringBootExceptionReporter> exceptionReporters,
512                             SpringApplicationRunListeners listeners) {
513                         try {
514                             try {
515                                 handleExitCode(context, exception);
516                                 if (listeners != null) {
517                                     listeners.failed(context, exception);
518                                 }
519                             }
520                             finally {
521                                 reportFailure(exceptionReporters, exception);
522                                 if (context != null) {
523                                     context.close();
524                                 }
525                             }
526                         }
527                         catch (Exception ex) {
528                             logger.warn("Unable to close ApplicationContext", ex);
529                         }
530                         ReflectionUtils.rethrowRuntimeException(exception);
531                     }
532                     //##############################################################      
533           throw new IllegalStateException(ex);
534         }
535 
536         try {
537           //第一次进来,listener只有1个
538           listeners.running(context);
539                     //##############################################################
540                     public void running(ConfigurableApplicationContext context) {
541                         for (SpringApplicationRunListener listener : this.listeners) {
542                             listener.running(context);
543                         }
544                     }
545                     //##############################################################
546                     --->EventPublishingRunListener
547                         public void running(ConfigurableApplicationContext context) {
548                             context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
549                         }
550                     
551           
552         }catch (Throwable ex) {
553           handleRunFailure(context, ex, exceptionReporters, null);
554           throw new IllegalStateException(ex);
555         }
556         return context;
557       }

 

  1 BootstrapApplicationListener
  2 
  3     @Override
  4     public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
  5         ConfigurableEnvironment environment = event.getEnvironment();
  6         if (!environment.getProperty("spring.cloud.bootstrap.enabled", Boolean.class,true)) {
  7             return;
  8         }
  9         // don't listen to events in a bootstrap context
 10         if (environment.getPropertySources().contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
 11             return;
 12         }
 13         ConfigurableApplicationContext context = null;
 14         String configName = environment.resolvePlaceholders("${spring.cloud.bootstrap.name:bootstrap}");
 15         for (ApplicationContextInitializer<?> initializer : event.getSpringApplication().getInitializers()) {
 16             if (initializer instanceof ParentContextApplicationContextInitializer) {
 17                 context = findBootstrapContext( (ParentContextApplicationContextInitializer) initializer, configName);
 18             }
 19         }
 20         //!!!!!!!!!!!!!!!! 在这里
 21         if (context == null) {
 22             context = bootstrapServiceContext(environment, event.getSpringApplication(),configName);
 23         }
 24         apply(context, event.getSpringApplication(), environment);
 25     }
 26     
 27     
 28     private ConfigurableApplicationContext bootstrapServiceContext(
 29             ConfigurableEnvironment environment, final SpringApplication application,
 30             String configName) {
 31         StandardEnvironment bootstrapEnvironment = new StandardEnvironment();
 32         MutablePropertySources bootstrapProperties = bootstrapEnvironment
 33                 .getPropertySources();
 34         for (PropertySource<?> source : bootstrapProperties) {
 35             bootstrapProperties.remove(source.getName());
 36         }
 37         String configLocation = environment
 38                 .resolvePlaceholders("${spring.cloud.bootstrap.location:}");
 39         Map<String, Object> bootstrapMap = new HashMap<>();
 40         bootstrapMap.put("spring.config.name", configName);
 41         // if an app (or test) uses spring.main.web-application-type=reactive, bootstrap will fail
 42         // force the environment to use none, because if though it is set below in the builder
 43         // the environment overrides it
 44         bootstrapMap.put("spring.main.web-application-type", "none");
 45         if (StringUtils.hasText(configLocation)) {
 46             bootstrapMap.put("spring.config.location", configLocation);
 47         }
 48         bootstrapProperties.addFirst(
 49                 new MapPropertySource(BOOTSTRAP_PROPERTY_SOURCE_NAME, bootstrapMap));
 50         for (PropertySource<?> source : environment.getPropertySources()) {
 51             if (source instanceof StubPropertySource) {
 52                 continue;
 53             }
 54             bootstrapProperties.addLast(source);
 55         }
 56         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
 57         // Use names and ensure unique to protect against duplicates
 58         List<String> names = new ArrayList<>(SpringFactoriesLoader
 59                 .loadFactoryNames(BootstrapConfiguration.class, classLoader));
 60         for (String name : StringUtils.commaDelimitedListToStringArray(
 61                 environment.getProperty("spring.cloud.bootstrap.sources", ""))) {
 62             names.add(name);
 63         }
 64         // TODO: is it possible or sensible to share a ResourceLoader?
 65         SpringApplicationBuilder builder = new SpringApplicationBuilder()
 66                 .profiles(environment.getActiveProfiles()).bannerMode(Mode.OFF)
 67                 .environment(bootstrapEnvironment)
 68                 // Don't use the default properties in this builder
 69                 .registerShutdownHook(false).logStartupInfo(false)
 70                 .web(WebApplicationType.NONE);
 71         if (environment.getPropertySources().contains("refreshArgs")) {
 72             // If we are doing a context refresh, really we only want to refresh the
 73             // Environment, and there are some toxic listeners (like the
 74             // LoggingApplicationListener) that affect global static state, so we need a
 75             // way to switch those off.
 76             builder.application().setListeners(filterListeners(builder.application().getListeners()));
 77         }
 78         List<Class<?>> sources = new ArrayList<>();
 79         for (String name : names) {
 80             Class<?> cls = ClassUtils.resolveClassName(name, null);
 81             try {
 82                 cls.getDeclaredAnnotations();
 83             }
 84             catch (Exception e) {
 85                 continue;
 86             }
 87             sources.add(cls);
 88         }
 89         AnnotationAwareOrderComparator.sort(sources);
 90         builder.sources(sources.toArray(new Class[sources.size()]));
 91         
 92         //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 93         //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 94         //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 95         final ConfigurableApplicationContext context = builder.run();
 96         
 97                 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 98                 public ConfigurableApplicationContext run(String... args) {
 99                     if (this.running.get()) {
100                         // If already created we just return the existing context
101                         return this.context;
102                     }
103                     configureAsChildIfNecessary(args);
104                     if (this.running.compareAndSet(false, true)) {
105                         synchronized (this.running) {
106                             // If not already running copy the sources over and then run.
107                             this.context = build().run(args);
108                             //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
109                                     /**
110                                      * Returns a fully configured {@link SpringApplication} that is ready to run.
111                                      * @return the fully configured {@link SpringApplication}.
112                                      */
113                                     public SpringApplication build() {
114                                         return build(new String[0]);
115                                     }
116                                     
117                                     这里又回到了SpringApplication的启动
118                                     
119                             //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
120                         }
121                     }
122                     return this.context;
123                 }
124                 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
125         
126         // gh-214 using spring.application.name=bootstrap to set the context id via
127         // `ContextIdApplicationContextInitializer` prevents apps from getting the actual
128         // spring.application.name
129         // during the bootstrap phase.
130         context.setId("bootstrap");
131         // Make the bootstrap context a parent of the app context
132         addAncestorInitializer(application, context);
133         // It only has properties in it now that we don't want in the parent so remove
134         // it (and it will be added back later)
135         bootstrapProperties.remove(BOOTSTRAP_PROPERTY_SOURCE_NAME);
136         mergeDefaultProperties(environment.getPropertySources(), bootstrapProperties);
137         return context;
138     }

 

SpringApplication.prepareEnvironment

1.listener.starting2.listener.environmentPrepared>>触发BootstrapApplicationListener,调用onApplicationEvent,  然后创建SpringApplicationBuilder builder = new SpringApplicationBuilder(), 又回到SpringApplication.run.  然后1,2(中间短路),3,4,5执行一遍.3.listener.contextPrepared>>context.refresh4.listener.started5.listener.running

 

posted @ 2020-08-11 20:15  multitude  阅读(433)  评论(0编辑  收藏  举报