在SpringApplication的實例屬性中有一個初始器的屬性:List<ApplicationContextInitializer<?>> initializers ,這些初始化器(initializers)是Spring Boot通過讀取每個jar包下的/META-INF/spring.factories文件中的配置獲取的。每一個initailizer都是一個實現了ApplicationContextInitializer接口的實例。ApplicationContextInitializer是Spring IOC容器中提供的一個接口:
package org.springframework.context; public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> { /** * Initialize the given application context. * @param applicationContext the application to configure */ void initialize(C applicationContext); }
ApplicationContextInitializer是一個回調接口,它會在ConfigurableApplicationContext的refresh()方法調用之前被調用,做一些容器的初始化工作。這一點我們也可以通過SpringApplication的實例run方法的實現代碼得到驗證,為了說明問題,再次貼一下這段代碼,注意下標紅的代碼和注釋就自然理解了。
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; FailureAnalyzers analyzers = null; configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); Banner printedBanner = printBanner(environment); context = createApplicationContext(); analyzers = new FailureAnalyzers(context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); // prepareContext方法中將會執行每個initializers的邏輯 refreshContext(context); // 執行bean的創建和實例化 afterRefresh(context, applicationArguments); listeners.finished(context, null); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } }
SpringBoot默認情況下提供了6個initializer,分別由2個jar提供:
spring-boot-1.5.2.RELEASE.jar
- org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,
- org.springframework.boot.context.ContextIdApplicationContextInitializer,
- org.springframework.boot.context.config.DelegatingApplicationContextInitializer,
- org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer
spring-boot-autoconfigure-1.5.2.RELEASE.jar
- org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,
- org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
Spring Boot對initializer的獲取過程如下:
initialize(Object[] sources)
-->(Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class )) //獲取initializer實例
-->SpringFactoriesLoader.loadFactoryNames(type, classLoader))
-->createSpringFactoriesInstances(type, parameterTypes,classLoader, args, names)
-->Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes)
-->T instance = (T) BeanUtils.instantiateClass(constructor, args)
-->AnnotationAwareOrderComparator.sort(instances)
--> setInitializers(Collection<? extends ApplicationContextInitializer<?>> initializers)
-->this.initializers = new ArrayList<ApplicationContextInitializer<?>>();
-->this.initializers.addAll(initializers); //存入List<ApplicationContextInitializer<?>> initializers