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

  • 相关阅读:
    为表增加列属性方法探究
    细聊冗余表数据一致性
    缓存架构设计细节二三事
    缓存与数据库一致性保证
    MySQL批量SQL插入性能优化
    Codeforces 1150
    Codeforces 1155
    Codeforces 331D
    Windows & Ubuntu Vscode 配置c++环境
    后缀数组
  • 原文地址:https://www.cnblogs.com/tekikesyo/p/13479765.html
Copyright © 2011-2022 走看看