zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    模拟赛总结
    2018.04.06学习总结
    2018.04.06学习总结
    Java实现 LeetCode 672 灯泡开关 Ⅱ(数学思路问题)
    Java实现 LeetCode 671 二叉树中第二小的节点(遍历树)
    Java实现 LeetCode 671 二叉树中第二小的节点(遍历树)
    Java实现 LeetCode 671 二叉树中第二小的节点(遍历树)
    Java实现 LeetCode 670 最大交换(暴力)
    Java实现 LeetCode 670 最大交换(暴力)
    Java实现 LeetCode 670 最大交换(暴力)
  • 原文地址:https://www.cnblogs.com/tekikesyo/p/13479765.html
Copyright © 2011-2022 走看看