一連のソーススプリングブート図2(a) - システムの初期化がApplicationContextInitializerあります

ApplicationContextInitializerドキュメントインターフェイスはそう書かれています:

ConfigurableApplicationContext#リフレッシュ()は、リフレッシュを実行する前に、図1に示すように、ApplicationContextInitializer AコールバックインターフェースをConfigurableApplicationContextを初期化するために使用されます。SpringApplication#prepareContext()メソッドは、初期化メソッドApplicationContextInitializer実装クラスを実行します。

一般的に、いくつかのアプリケーションプログラムのコンテキストで必要な2は、ソースレジスタまたは活性化プロファイルのConfigurableApplicationContext#GetEnvironment関数()の性質のために、例えばWebアプリケーションを初期化します。

3は、システムの初期化は、呼び出しの前にソートするために、例えばノート@Order org.springframework.core.Ordered順序インターフェイスまたは使用を、達成することが奨励されます。

図示していない場合、ApplicationContextInitializerはそれが何を意味するのかと言うとのインタフェース文書を理解することは困難です。それは今、それがシステムの初期化を使用する方法の3種類をご紹介し始めました。

最初:使用spring.factories設定

1、新しいFirstInitializer ApplicationContextInitializerインタフェースを実現

/**
 * 使用@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 运行");
    }

}

resourcesディレクトリに2、新/META-INF/spring.factoriesディレクトリとファイル

spring.factoriesに追加

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

3、次のようにプロパティ値を取得:

@value( "$ {KEY1}")
文字列KEY1。

4、プロジェクトを開始、値を得ることができるようになります。

図5は、@Orderを使用せずに、インタフェースは順序ソートすることにより実現しました。新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、spring.factoriesを追加

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

7、プログラムを実行し、コンソール出力

############# FirstInitializer.initializeラン
############# FirstOrderedInitializer.initialize実行

ソート値@Order使用FirstInitializer注釈1、FirstOrderedInitializer#getOrder()リターン11です。それは見ることができます:ソートの値が小さいほど、最初に行きました。

第二:ハードコーディングaddInitializers(新しいSecondInitializer())。

1、新しい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に示すように、コード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);
    }

}

第三:application.propertiesに配置されたcontext.initializer.classes

1、新しい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 运行");
    }
}

application.propertiesに配置された2

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

3、コンソール出力以下、プロジェクトを開始

############# ThirdInitializer.initialize実行
############# FirstInitializer.initialize実行
############# SecondInitializer.initialize実行
############# FirstOrderedInitializer.initialize実行

ThirdInitializerコメントはFirstInitializer、SecondInitializer最初の実行よりも@Order(3)が、ThirdInitializerです。初期化context.initializer.classes構成の使用が最初にそれを実行しますではないですか?この質問は、後に回答されます。

ソースを説明しました

春のブートバージョン2.2.4.RELEASEです。

ファーストクラスのコードは、バックSpringBootDemoApplication.javaに起動します 

SpringApplication.run(SpringBootDemoApplication.class、引数)。

春のブーツは、ほとんどの従来の起動モードを使用して、ソースコードを分析します。

1、runメソッドに、次のコードが表示されるまで。

// 源码位置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);
}

大体それを結論付けることができ、コードSpringApplication.run(SpringBootDemoApplication.class、引数)を使用して、春ブーツ、プロジェクトを開始するには、自然の中でSpringApplicationインスタンスを作成し、runメソッドのインスタンスを実行することです。実行されるメソッドを実行し、開始したプロジェクトを完了しました。

1.1、デバッグに進み、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ソース:

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

1.1.2、getSpringFactoriesInstances(ApplicationListener.class)取得システム初期化の関数であります

メソッドのデバッグの体内に

// 源码位置 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、クラスローダクラスローダ=のgetClassLoader()。

getClassLoader()は、結果AppClassLoaderインスタンスを返します。
BootstrapClassLoader、ExtClassLoader、AppClassLoader:Javaは3クラスローダが付属しています。AppClassLoader負荷のクラスパスの下のクラスファイルとディレクトリのjarパッケージ。我々は通常、それによってロードされているサードパーティのjarパッケージコードとコードの依存関係を書かれています。
ランはSystem.getProperty(「のjava.class.path」)は、見るためにどのような現在のプロジェクトのクラスパスはい。

1.1.2.2、設定<文字列>名=新しいLinkedHashSetの<>(SpringFactoriesLoader.loadFactoryNames(タイプ、クラスローダ));

タイプは、このコードのApplicationContextInitializerインタフェースはクラスのコレクション型インタフェースの実装クラスの完全な名前を取得することです。インテリア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());
}

デバッグloadSpringFactories(クラスローダー)内部へ

// 源码位置 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);
	}
}

これは、設定<文字列>名=新しいLinkedHashSetの<>(SpringFactoriesLoader.loadFactoryNames(タイプ、クラスローダ))結論;このコード行の役割を。大雑把に以下の二つの小さなステップに分け:

クラスパスのパス内の1、AppClassLoader GET spring.factoriesファイル

2、spring.factoriesのプロパティを読み、オブジェクトを作成します

図3は、インターフェイスタイプ(この記事はApplicationContextInitializerされるタイプ)の実装クラスの完全な名前は、クラスを返します。結果セット<文字列>タイプですのでApplicationContextInitializerは、クラスの完全なクラス名を実現するように構成するサードパーティのjarパッケージspring.factoriesは、読んで返されます。

1.1.2.3、リスト<T>インスタンス= createSpringFactoriesInstances(タイプ、parameterTypesパラメータ、クラスローダ、引数、名前);

次のようにクラス全体の収集システムの初期化の名前を取得し、あなたが収集システムの初期化のインスタンスを作成することができ、ソースコードは次のとおりです。

// 源码位置 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(インスタンス);これは、初期セットがソートされているシステムの一例です。

デバッグに次のコード

// 源码位置 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);
}

次のコードでマークされたブレークポイントでは、プログラムの実行、デバッグ
com.example.springbootdemo.FirstOrderedInitializer getOrder#()
    //呼び出しgetOrderは、ランキング値の取得、実装クラス()メソッドを発注 
    リターン2を、     
org.springframework.core.annotation.OrderUtils# findOrder()
    のアノテーション@Orderの値を取得する// getOrder方法 
    MergedAnnotation <オーダー> orderAnnotation = annotations.get(Order.class)を、
    IF(orderAnnotation.isPresent()){
        リターンorderAnnotation.getInt(MergedAnnotation.VALUE);
    }

この時点で、システムの初期化コードは、それが終了しています初期化します。フォーカスがgetSpringFactoriesInstances方法で、次のようにこれを行うための方法をまとめたものです。

// 源码位置 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原理はSpringApplication.initializersに追加されましたはっきり話します。

SecondInitializerは、springApplication.addInitializers(新しいSecondInitializer())SpringApplication.initializers非常に簡単な方法に加え、ソース次のように

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

現在、2つの質問を残しました:

図1に示すように、SecondInitializer:のaddAll SecondInitializerが間違った位置に仕分け、this.initializersの末尾に追加されます。

2は、ThirdInitializerはapplication.properties構成によって、それはthis.initializersに追加されていません。

これら二つの質問では、我々は新しいSpringApplication(primarySources).RUN(引数)を探求する必要があり、runメソッド、SpringApplicationのすなわち運用段階。

使用SpringApplication.run(SpringBootDemoApplication.class、引数);プログラムを起動します。ソースコードに新しいSpringApplication(primarySources).RUN(引数)を実行し、前述の第二の構成は、システムの初期化コードと、このコードは、にクラスコードを開始する必要が構成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);  // 这句代码打上断点调试
    }

}

springApplication.runでは(引数);このコードのブレークポイントでマークされ、エンジニアリング、試運転を開始します。

デバッグを実行する方法

// 源码位置 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);
}

prepareContextにデバッグプロセス

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

}

applyInitializers方法出典:

// 源码位置 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()システム初期化、システムの初期化のためのシステムを取得し、再びソート

// 源码位置 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は、システムの初期化の最初の行はDelegatingApplicationContextInitializerあり、それは指定された環境プロパティcontext.initializer.classes初期化動作に委任される(委譲システム初期化、順序値は0です)初期化子。

ソースDelegatingApplicationContextInitializer.initializeとしてメソッド

// 源码位置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(環境)、ソースコード解析

// 源码位置 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(コンテキスト、initializerClasses);ソース分析

// 源码位置 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(コンテキスト、初期化子);ソース分析

// 源码位置 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が呼び出されました。今DelegatingApplicationContextInitializer(デリゲートシステム初期化装置)の概要を可能にします。

1、DelegatingApplicationContextInitializerランキング値は、FirstInitializerより小さいランキング値SecondInitializer、呼び出される最初0です。

2、DelegatingApplicationContextInitializerシステム構成初期context.initializer.classesをインスタンス化し、これらのシステムの動作は、メソッドイニシャライザを初期化します。context.initializer.classesよう構成されたシステムの初期化は、最初に実行されます。

ランキング値セットFirstInitializerが0未満であれば3、DelegatingApplicationContextInitializer順位値が操作は、まず、FirstInitializer 0ますあります。

完成インスタンス化、プロセスThirdInitializerを実行します。バックorg.springframework.boot.SpringApplication#applyInitializers方法では、プロセスはFirstInitializerを実行し続けて説明し、FirstOrderedInitializerのSecondInitializer

// 源码位置 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);
    }
}

さて、春ブーツ2システムの初期化は、ソースコードを使用することですが終了し、私は戻って更新していきます春のブートソースのシリーズを  、歓迎交換します。

 

 

公開された51元の記事 ウォン称賛14 ビュー40000 +

おすすめ

転載: blog.csdn.net/u010606397/article/details/105103629