fuente de la serie de primavera de arranque 2 (a) - la inicialización del sistema es ApplicationContextInitializer

interfaz de documentos ApplicationContextInitializer Así está escrito:

1, ApplicationContextInitializer una interfaz de devolución de llamada se utiliza para inicializar ConfigurableApplicationContext antes ConfigurableApplicationContext # refresh () realizar una renovación. Método # SpringApplication prepareContext () llevará a cabo la clase de implementación del método initialize ApplicationContextInitializer.

2, se requiere generalmente en el contexto de algún programa de aplicación inicializa la aplicación Web, por ejemplo para ConfigurableApplicationContext # getEnvironment () propiedades del registro de perfil de origen o de activación.

3, se recomienda la inicialización del sistema para lograr interfaz Ordenadas org.springframework.core.Ordered o utilizar notas @Order, por ejemplo con el fin de ser resuelto antes de la llamada.

Si no se ilustra, es difícil entender el documento ApplicationContextInitializer interfaces de decir lo que significa. Ahora comenzó a introducir tres tipos de formas de utilizar el sistema de inicialización es la misma.

La primera: el uso de configuración spring.factories

1, el nuevo FirstInitializer lograr ApplicationContextInitializer Interface

/**
 * 使用@Order注解(第3点)
 */
@Order(1)
public class FirstInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    /**
     * 在resources目录下新建/META-INF/spring.factories目录与文件。
     * 在resources/META-INF/spring.factories配置:
     * org.springframework.context.ApplicationContextInitializer=com.example.springbootdemo.FirstInitializer
     *
     * spring.factories的配置规则是: 接口全名=实现类全名
     */
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        /**
         * 本方法代码是添加属性 key1=value1。
         *
         * 可通过以下方式获取添加的属性:
         * @Value("${key1}")
         * String key1;
         */
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        Map<String, Object> map = new HashMap<>();
        map.put("key1", "value1");

        // 新建属性源,并添加属性源。(第2点)
        MapPropertySource mps = new MapPropertySource("firstInitializer", map);
        environment.getPropertySources().addLast(mps);

        System.out.println("#############FirstInitializer.initialize 运行");
    }

}

2, directorio Nuevos /META-INF/spring.factories y archivo en el directorio de recursos

Añadir en los spring.factories

org.springframework.context.ApplicationContextInitializer = com.example.springbootdemo.FirstInitializer

3, obteniendo un valor de propiedad de la siguiente manera:

@Value ( "$ {} key1")
Cadena key1;

4, iniciar el proyecto, será capaz de obtener el valor.

5, sin utilizar el @Order, interfaz implementada mediante clasificación ordenada. nueva FirstOrderedInitializer.java

/**
 * 通过实现Ordered接口实现排序
 */
public class FirstOrderedInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        System.out.println("#############FirstOrderedInitializer.initialize 运行");
    }

    // 返回排序值
    @Override
    public int getOrder() {
        return 11;
    }
}

6, añadir los spring.factories

org.springframework.context.ApplicationContextInitializer = com.example.springbootdemo.FirstInitializer, \
com.example.springbootdemo.FirstOrderedInitializer

7, ejecute el programa, la salida de la consola

############# FirstInitializer.initialize plazo
############# FirstOrderedInitializer.initialize plazo

FirstInitializer anotación utilizando valor de ordenación @Order es 1, FirstOrderedInitializer # getOrder () devuelve 11. Se puede ver: cuanto menor sea el valor de la clase representada por primera vez.

El segundo: addInitializers codificados duros (nuevo SecondInitializer ());

1, el nuevo SecondInitializer.java

@Order(2)
public class SecondInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {

        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        Map<String, Object> map = new HashMap<>();
        map.put("key2", "value2");

        MapPropertySource mps = new MapPropertySource("secondInitializer", map);
        environment.getPropertySources().addLast(mps);

        System.out.println("#############SecondInitializer.initialize 运行");
    }
}

2, la modificación de la clase de arranque, añadiendo el código SecondInitializer

@SpringBootApplication
public class SpringBootDemoApplication {

    public static void main(String[] args) {

        //SpringApplication.run(SpringBootDemoApplication.class, args);

        // 第2中添加系统初始化器的方式
        SpringApplication springApplication = new SpringApplication(SpringBootDemoApplication.class);
        springApplication.addInitializers(new SecondInitializer());
        springApplication.run(args);
    }

}

Tercero: context.initializer.classes dispuestos en application.properties

1, el nuevo ThirdInitializer.java

@Order(3)
public class ThirdInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {

        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        Map<String, Object> map = new HashMap<>();
        map.put("key3", "value3");

        MapPropertySource mps = new MapPropertySource("thirdInitializer", map);
        environment.getPropertySources().addLast(mps);

        System.out.println("#############ThirdInitializer.initialize 运行");
    }
}

2, dispuesto en la application.properties

context.initializer.classes = com.example.springbootdemo.ThirdInitializer

3, iniciar el proyecto, después de la salida de la consola

############# ThirdInitializer.initialize plazo
############# FirstInitializer.initialize plazo
############# SecondInitializer.initialize plazo
############# plazo FirstOrderedInitializer.initialize

ThirdInitializer comentario es @Order (3), pero que ThirdInitializer FirstInitializer, SecondInitializer primera carrera. No es el uso de la configuración context.initializer.classes inicializador primero se lo lleva? Esta pregunta será respondida más tarde.

fuente explicó

versión de arranque de primavera es 2.2.4.RELEASE.

Iniciar la parte posterior de código de primera clase a SpringBootDemoApplication.java 

SpringApplication.run (SpringBootDemoApplication.class, args);

Primavera de arranque para analizar el código fuente usando el modo de puesta en marcha más convencional.

1, en el método de ejecución, hasta que vea el siguiente código:

// 源码位置org.springframework.boot.SpringApplication#run(java.lang.Class<?>[], java.lang.String[])
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
	return new SpringApplication(primarySources).run(args);
}

Se puede concluir que más o menos, la primavera de arranque utilizando un código SpringApplication.run (SpringBootDemoApplication.class, args); iniciar el proyecto es la creación de instancias SpringApplication en la naturaleza, y luego ejecutar la instancia método run. ejecutar el método ejecutado, terminado el proyecto iniciado.

1.1, siguen depuración, introduzca constructor SpringApplication

// 源码位置 org.springframework.boot.SpringApplication#SpringApplication(org.springframework.core.io.ResourceLoader, java.lang.Class<?>...)
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    // 这行代码就是设置初始化器
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = deduceMainApplicationClass();
}

1.1.1, setInitializers fuente siguiente métodos:

// 源码位置 org.springframework.boot.SpringApplication#setInitializers
public void setInitializers(Collection<? extends ApplicationContextInitializer<?>> initializers) {
	/**
	 * 系统初始化器可以有多个,形成一个系统初始化器列表。
	 * 在创建SpringApplication对象时,将系统初始化器列表赋值给SpringApplication的initializers属性。
	 */
    this.initializers = new ArrayList<>(initializers);
}

1.1.2, getSpringFactoriesInstances sistema de adquisición (ApplicationListener.class) es una función de la inicialización

En el cuerpo de la depuración método

// 源码位置 org.springframework.boot.SpringApplication#getSpringFactoriesInstances(java.lang.Class<T>, java.lang.Class<?>[], java.lang.Object...)
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
	ClassLoader classLoader = getClassLoader();
	// Use names and ensure unique to protect against duplicates
	Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
	List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
	AnnotationAwareOrderComparator.sort(instances);
	return instances;
}

1.1.2.1, ClassLoader cargador de clases = getClassLoader ();

getClassLoader () devuelve una instancia resultado AppClassLoader.
Java viene con tres cargador de clases: BootstrapClassLoader, ExtClassLoader, AppClassLoader. AppClassLoader paquete de archivos de clase de cargas y directorios frasco bajo la ruta de clases. Hemos escrito un código de paquete frasco de terceros y dependencias de código son por lo general cargado por ella.
Ejecutar System.getProperty ( "java.class.path"), para ver lo que el actual proyecto de ruta de clases Sí.

1.1.2.2, Set <String> nombres = new LinkedHashSet <> (SpringFactoriesLoader.loadFactoryNames (tipo, cargador de clases));

Tipo de interfaz es ApplicationContextInitializer de este código es obtener el nombre completo de la clase de implementación de interfaz de tipo de colección de clases. En el método de interiores SpringFactoriesLoader.loadFactoryNames.

// 源码位置 org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
    String factoryTypeName = factoryType.getName();
    /**
     * 重点代码是 loadSpringFactories(classLoader)。
     * 先讲结论,loadSpringFactories(classLoader)返回一个LinkedMultiValueMap对象,此对象一个key对应多个value。
     * key是接口全类名,value是接口的实现类全类名,value可以有多个。
     */
    return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}

Para depurar loadSpringFactories (cargador de clases) Interno

// 源码位置 org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
	MultiValueMap<String, String> result = cache.get(classLoader);
	if (result != null) {
		return result;
	}

	try {
		/**
		 * FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
		 * 通过AppClassLoader加载Classpath下的META-INF/spring.factories
		 * 当前工程和依赖的第三方jar包中的META-INF/spring.factories都会被加载进来
		 */
		Enumeration<URL> urls = (classLoader != null ?
				classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
				ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
		result = new LinkedMultiValueMap<>();
		while (urls.hasMoreElements()) {
			URL url = urls.nextElement();
			// resource是包含了spring.factories文件路径的资源对象
			UrlResource resource = new UrlResource(url);
			// 使用spring.factories中配置的键值对创建Properties对象
			Properties properties = PropertiesLoaderUtils.loadProperties(resource);
			// 循环properties的键值对
			for (Map.Entry<?, ?> entry : properties.entrySet()) {
				String factoryTypeName = ((String) entry.getKey()).trim();
				for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
					/**
					 * factoryTypeName是spring.factories中配置的key,比如:ApplicationContextInitializer接口全类名
					 * factoryImplementationName是key对应的value,比如:ApplicationContextInitializer实现类FirstInitializer的全类名
					 */
					result.add(factoryTypeName, factoryImplementationName.trim());
				}
			}
		}
		cache.put(classLoader, result);
		
        /**
		 * result是一个LinkedMultiValueMap。key是接口全名,value是接口的实现类全类名,value可以是多个。
		 * 需要注意的是:
		 * 1、AppClassLoader会获取Classpath下所有jar包的spring.factories文件
		 * 2、并将spring.factories中所有的配置添加到result中
		 * 基于以上两点,就不难理解为什么要用缓存了
		 * cache.put(classLoader, result); 、 MultiValueMap<String, String> result = cache.get(classLoader);
		 * AppClassLoader把classpath下所有的spring.factories读取到缓存中。下次要用spring.factories配置时,从缓存中拿就好了
		 */
		return result;
	}
	catch (IOException ex) {
		throw new IllegalArgumentException("Unable to load factories from location [" +
				FACTORIES_RESOURCE_LOCATION + "]", ex);
	}
}

Con esto concluye el conjunto <String> nombres = new LinkedHashSet <> (SpringFactoriesLoader.loadFactoryNames (tipo, cargador de clases)); el papel de esta línea de código. Más o menos dividido en las siguientes dos pequeños pasos:

1, AppClassLoader get spring.factories archivos en la ruta de la ruta de clases

2, leer las propiedades spring.factories y crear objetos

3, el tipo de interfaz (escriba este artículo es ApplicationContextInitializer) el nombre completo de la clase de implementación devuelve la clase. Terceros spring.factories paquete frasco configurados ApplicationContextInitializer lograr nombre completo de la clase de la clase será leído y regresó, por lo que el resultado es un conjunto <String> Tipo.

1.1.2.3, List <T> casos = createSpringFactoriesInstances (tipo, parameterTypes, cargador de clases, args, nombres);

Recibe el nombre de la inicialización del sistema de recogida de toda la clase, puede crear una instancia de la inicialización del sistema de recogida, el código fuente es el siguiente:

// 源码位置 org.springframework.boot.SpringApplication#createSpringFactoriesInstances
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
		ClassLoader classLoader, Object[] args, Set<String> names) {
	List<T> instances = new ArrayList<>(names.size());
	for (String name : names) {
		try {
			// AppClassLoader使用类全名把类加载到jvm内存中
			Class<?> instanceClass = ClassUtils.forName(name, classLoader);
			Assert.isAssignable(type, instanceClass);
			// 获取系统初始化器的构造器
			Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
			// 通过构造器创建实例
			T instance = (T) BeanUtils.instantiateClass(constructor, args);
			// 添加到集合中
			instances.add(instance);
		}
		catch (Throwable ex) {
			throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
		}
	}
    // 返回系统初始化器实例集合
	return instances;
}

1.1.2.4, AnnotationAwareOrderComparator.sort (instancias); Este es un ejemplo de conjunto de la inicialización del sistema está ordenada.

el siguiente código de depuración

// 源码位置 org.springframework.core.OrderComparator#doCompare()
private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
	boolean p1 = (o1 instanceof PriorityOrdered);
	boolean p2 = (o2 instanceof PriorityOrdered);
	if (p1 && !p2) {
		return -1;
	}
	else if (p2 && !p1) {
		return 1;
	}

	/**
	 * getOrder方法很复杂,本文只关注getOrder方法的两个作用。
	 * 1、获取@Order注解值
	 * 2、获取Ordered接口getOrder方法返回值
	 */
	int i1 = getOrder(o1, sourceProvider);
	int i2 = getOrder(o2, sourceProvider);

	// 排序规则是升序
	return Integer.compare(i1, i2);
}

En el siguiente código marcado punto de ruptura, la ejecución del programa de depuración
com.example.springbootdemo.FirstOrderedInitializer getOrder # ()
    método // llamada getOrder ordenada clase de implementación (), obteniendo el valor de clasificación 
    de retorno 2;     
org.springframework.core.annotation.OrderUtils # findOrder ()
    método // getOrder para obtener el valor de la anotación @Order 
    MergedAnnotation <la Orden> orderAnnotation = annotations.get (Order.class);
    SI (orderAnnotation.isPresent ()) {
        orderAnnotation.getInt retorno (MergedAnnotation.VALUE);
    }

En este punto, el código de inicialización del sistema para inicializar esté terminado. El enfoque es el método getSpringFactoriesInstances, a continuación se resume las maneras de hacer esto:

// 源码位置 org.springframework.boot.SpringApplication#getSpringFactoriesInstances(java.lang.Class<T>, java.lang.Class<?>[], java.lang.Object...)
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
	// getClassLoader()返回AppClassLoader
	ClassLoader classLoader = getClassLoader();
	// 获取系统初始化器全类名集合
	Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
	// 创建系统初始化器集合
	List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
	// 对系统初始化器排序
	AnnotationAwareOrderComparator.sort(instances);
	// 返回排序后的系统初始化器集合
	return instances;
}

FirstInitializer principio ha sido añadido a SpringApplication.initializers hablan claramente.

SecondInitializer añadió a las SpringApplication.initializers manera muy simple, springApplication.addInitializers (SecondInitializer nuevo ()); fuente como sigue:

// 源码位置 org.springframework.boot.SpringApplication#addInitializers
public void addInitializers(ApplicationContextInitializer<?>... initializers) {
	this.initializers.addAll(Arrays.asList(initializers));
}

Actualmente dejado atrás a dos preguntas:

1, SecondInitializer: addAll SecondInitializer se añade al final de los this.initializers, la clasificación de la posición incorrecta.

2, ThirdInitializer por la configuración application.properties, no ha sido añadido a las this.initializers.

Con estas dos preguntas, tenemos que explorar nuevas SpringApplication (primarySources) .run (args); método de ejecución, es decir, la fase operativa de SpringApplication.

Uso SpringApplication.run (SpringBootDemoApplication.class, args); iniciar el programa. En el código fuente se ejecuta nuevo SpringApplication (primarySources) .run (args); este código con la segunda configuración descrita anteriormente, el código de inicialización del sistema es muy similar a la configuración SecondInitializer, necesidad de iniciar el código de clase en

@SpringBootApplication
public class SpringBootDemoApplication {

    public static void main(String[] args) {

        //SpringApplication.run(SpringBootDemoApplication.class, args);

        // 第2中添加系统初始化器的方式
        SpringApplication springApplication = new SpringApplication(SpringBootDemoApplication.class);
        springApplication.addInitializers(new SecondInitializer());
        springApplication.run(args);  // 这句代码打上断点调试
    }

}

En springApplication.run (args); marcada con este código de puntos de ruptura, iniciar la ingeniería y puesta en marcha.

Método para ejecutar la depuración

// 源码位置 org.springframework.boot.SpringApplication.run(java.lang.String...)
public ConfigurableApplicationContext run(String... args) {
    /**
     * run方法很复杂,本文作为spring boot源码系列的第一篇博客,仅关注系统初始化器相关代码。其他代码忽略
     * prepareContext方法内会运行系统初始化器
     */
    prepareContext(context, environment, listeners, applicationArguments, printedBanner);
    // ApplicationContextInitializer接口文档第三点
    refreshContext(context);
}

proceso de depuración para prepareContext

// 源码位置 org.springframework.boot.SpringApplication.prepareContext
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
                            SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
    // 应用初始化器
    applyInitializers(context);

}

applyInitializers método Fuente:

// 源码位置 org.springframework.boot.SpringApplication#applyInitializers
protected void applyInitializers(ConfigurableApplicationContext context) {
	/**
	 * getInitializers()获取系统初始化器,并且对系统系统初始化器再次排序,解决了SecondInitializer的排序问题
	 * 循环系统初始化器,并执行系统初始化器的initialize方法
	 */
	for (ApplicationContextInitializer initializer : getInitializers()) {
		Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
				ApplicationContextInitializer.class);
		Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
		initializer.initialize(context);
	}
}

1, getInitializers () obtiene la inicialización del sistema, un sistema para la inicialización del sistema y se clasifican de nuevo

// 源码位置 org.springframework.boot.SpringApplication#asUnmodifiableOrderedSet 
private static <E> Set<E> asUnmodifiableOrderedSet(Collection<E> elements) {
	List<E> list = new ArrayList<>(elements);
	// 再次对系统初始化器集合排序
	list.sort(AnnotationAwareOrderComparator.INSTANCE);
	return new LinkedHashSet<>(list);
}

2, getInitializers () para obtener un conjunto de dispositivo de inicialización del sistema, la primera fila de la inicialización del sistema es DelegatingApplicationContextInitializer (delegar inicializador sistema, el valor de orden es 0), se delegan en la operación de inicialización especificados propiedades de entorno context.initializer.classes inicializador.

Método como DelegatingApplicationContextInitializer.initialize fuente

// 源码位置org.springframework.boot.context.config.DelegatingApplicationContextInitializer#initialize
public void initialize(ConfigurableApplicationContext context) {
	// 获取环境变量
	ConfigurableEnvironment environment = context.getEnvironment();
	// 获取context.initializer.classes配置的初始化器集合
	List<Class<?>> initializerClasses = getInitializerClasses(environment);
	if (!initializerClasses.isEmpty()) {
		// 执行初始化器的initialize方法
		applyInitializerClasses(context, initializerClasses);
	}
}

2.1 getInitializerClasses (medio ambiente); análisis de código fuente

// 源码位置 org.springframework.boot.context.config.DelegatingApplicationContextInitializer#getInitializerClasses
private List<Class<?>> getInitializerClasses(ConfigurableEnvironment env) {
	// PROPERTY_NAME = "context.initializer.classes"
	String classNames = env.getProperty(PROPERTY_NAME);
	List<Class<?>> classes = new ArrayList<>();
	if (StringUtils.hasLength(classNames)) {
		// 通过","分隔context.initializer.classes的值
		for (String className : StringUtils.tokenizeToStringArray(classNames, ",")) {
			// getInitializerClass(className)使用AppClassLoader加载类
			classes.add(getInitializerClass(className));
		}
	}
	return classes;
}

2.2, applyInitializerClasses (contexto, initializerClasses); análisis de la fuente

// 源码位置 org.springframework.boot.context.config.DelegatingApplicationContextInitializer#applyInitializerClasses
private void applyInitializerClasses(ConfigurableApplicationContext context, List<Class<?>> initializerClasses) {
	Class<?> contextClass = context.getClass();
	List<ApplicationContextInitializer<?>> initializers = new ArrayList<>();
	// initializerClasses是context.initializer.classes指定的类集合
	for (Class<?> initializerClass : initializerClasses) {
		// 实例化系统初始化器
		initializers.add(instantiateInitializer(contextClass, initializerClass));
	}
	// 应用系统初始化器
	applyInitializers(context, initializers);
}

2.2.1 applyInitializers (contexto, inicializadores); análisis de la fuente

// 源码位置 org.springframework.boot.context.config.DelegatingApplicationContextInitializer#applyInitializers
private void applyInitializers(ConfigurableApplicationContext context,
		List<ApplicationContextInitializer<?>> initializers) {
	// 先排序,这里是对context.initializer.classes配置的系统初始化器进行排序
	initializers.sort(new AnnotationAwareOrderComparator());
	for (ApplicationContextInitializer initializer : initializers) {
		// 执行初始化器的initialize方法,会进入 ThirdInitializer#initialize 方法中
		initializer.initialize(context);
	}
}

ThirdInitializer fue llamado. Ahora, para ser un resumen de DelegatingApplicationContextInitializer (delegado dispositivo de inicialización del sistema):

1, DelegatingApplicationContextInitializer valor de clasificación es 0, el valor de clasificación SecondInitializer menor que FirstInitializer, el primero en ser llamado.

2, DelegatingApplicationContextInitializer instanciado context.initializer.classes inicializador configuración del sistema, y ​​el funcionamiento de estos sistemas inicializar método inicializador. Así context.initializer.classes primero ejecutará configurado la inicialización del sistema.

3, DelegatingApplicationContextInitializer valor de clasificación es 0, si el valor de ajuste clasificación FirstInitializer es menor que 0, la operación primera FirstInitializer.

instanciación finalizado, ejecute el proceso ThirdInitializer. En el método # applyInitializers volver org.springframework.boot.SpringApplication, explicar el proceso continúa funcionando FirstInitializer, FirstOrderedInitializer, SecondInitializer de

// 源码位置 org.springframework.boot.SpringApplication#applyInitializers
protected void applyInitializers(ConfigurableApplicationContext context) {
    /**
     * 循环处理getInitializers()返回的系统初始化器,
     * 排在第一位的是DelegatingApplicationContextInitializer,前面已经讲了此初始化器的运行过程
     * 后面几次循环获得的initializer包含FirstInitializer、FirstOrderedInitializer、SecondInitializer
     * initializer.initialize(context);就直接运行我们自定义的系统初始化器了
     */
    for (ApplicationContextInitializer initializer : getInitializers()) {
        Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
                ApplicationContextInitializer.class);
        Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
        initializer.initialize(context);
    }
}

Bueno, arranque muelle 2 inicialización del sistema es usar el código fuente se termine, voy a seguir para actualizar la parte posterior serie Fuente de inicio de la primavera  , da la bienvenida al cambio.

 

 

Publicado 51 artículos originales · elogios ganado 14 · Vistas a 40000 +

Supongo que te gusta

Origin blog.csdn.net/u010606397/article/details/105103629
Recomendado
Clasificación