Springコアポストプロセッサ-ConfigurationClassPostProcessor

このブログは機能が限られているため、不完全なものもありますが、お役に立てば幸いです。
プロセッサの継承図を見てみましょう

このツールクラスには、2つの非常に重要なプロパティがありますorg.springframework.context.annotation.ConfigurationClassUtils

	private static final String CONFIGURATION_CLASS_FULL = "full";

	private static final String CONFIGURATION_CLASS_LITE = "lite";

これらの2つの属性を説明する方法

いっぱい、私たちはそれをすべてとして理解することができ、春の対応するライトも一部として理解することができます

では、主人公の@Configurationアノテーションとこれら2つの属性の関係は何ですか?構成クラスに追加する場合と追加しない場合に、Spring環境が有効になるのはなぜですか?

最初に環境内のコードを見てみましょう

@Configuration
//@Import(TestImportSelector.class)
//@TestImportSelectorAnno
//@TestBeanFactoryPostProcessorAnno
@ComponentScan("org.springframework.test.main.*")
public class ScanConfig {
}

//测试

public class MainDemo {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext ac =
				new AnnotationConfigApplicationContext(ScanConfig.class);
		ScanConfig scanConfig = (ScanConfig) ac.getBean("scanConfig");

	}

}

このクラスのこのコードのブレークポイントを入力してデバッグしましょう

	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		int factoryId = System.identityHashCode(beanFactory);
		if (this.factoriesPostProcessed.contains(factoryId)) {
			throw new IllegalStateException(
					"postProcessBeanFactory already called on this post-processor against " + beanFactory);
		}
		this.factoriesPostProcessed.add(factoryId);
		if (!this.registriesPostProcessed.contains(factoryId)) {
			// BeanDefinitionRegistryPostProcessor hook apparently not supported...
			// Simply call processConfigurationClasses lazily at this point then.
            //断点调式
			processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
		}
		//给配置类产生cglib代理。加了@Configuration注解的
		enhanceConfigurationClasses(beanFactory);
		beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
	}

 

通常の状況では、このコードは、春の設計の厳密さのために、登録リスト(BeanDefinition)内のすべてのbdを解析し、検出されたクラスと@Configurationアノテーションを別のbdコレクションに配置する場合にのみelseに入ります。次へ進む分析。検出では、注釈付きのクラスの属性であるisFull(省略形)が設定され、そうでないものはlite(これも断続的)属性です。次のブレークポイント分析に進みます。

このタイプのソースコードの2番目の分析

	public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
		Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
		for (String beanName : beanFactory.getBeanDefinitionNames()) {
			BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
			if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
				if (!(beanDef instanceof AbstractBeanDefinition)) {
					throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +
							beanName + "' since it is not stored in an AbstractBeanDefinition subclass");
				}
				else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
					logger.info("Cannot enhance @Configuration bean definition '" + beanName +
							"' since its singleton instance has been created too early. The typical cause " +
							"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
							"return type: Consider declaring such methods as 'static'.");
				}
				configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
			}
		}
		if (configBeanDefs.isEmpty()) {
			// nothing to enhance -> return immediately
			return;
		}

このコードはこのように理解できます。@ Configurationを含むクラスをマップに配置します。空の場合は直接返され、空でない場合は次のコードを入力します。

次のコードは投稿されません。後で結果がわかり、ブレークポイントはテストクラスに戻ります。イースターエッグを見てみましょう

 

はい、cglibプロキシです。追加しない場合はそうではありません。結果を見てください。

なぜですか?これは、春の厳密さ(シングルトン原理)の長所の1つです。まず、次のコードを見てみましょう。

初期化された環境コードを見てください

@Configuration
@ComponentScan("org.springframework.test.main.*")
public class ScanConfig {

	@Bean
	public Test getTestBean(){
		return new Test();
	}

	@Bean
	public User getUserBean(){
		return new User();
	}
}

public class Test {

	public Test(){}
}

public class User {

	public User(){
		System.out.println("init-user");
	};
}

public class MainDemo {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext ac =
				new AnnotationConfigApplicationContext(ScanConfig.class);
	}

}

このコメントが追加されているかどうかに関係なく、変更すると、印刷結果はすべてinit-userになります。

@Configuration
@ComponentScan("org.springframework.test.main.*")
public class ScanConfig {

	@Bean
	public Test getTestBean(){
		getUserBean();
		return new Test();
	}

	@Bean
	public User getUserBean(){
		return new User();
	}
}
//cglib此结果会打印一次.加入static关键字会失效

@ComponentScan("org.springframework.test.main.*")
public class ScanConfig {

	@Bean
	public Test getTestBean(){
		getUserBean();
		return new Test();
	}

	@Bean
	public User getUserBean(){
		return new User();
	}
}
//此结果会打印两次

しかし、問題があります。出力される2つのハッシュコードは同じであり、同じものがシングルトンのオブジェクトです。

レベルが限られているため、本当の理由は不明です

2つのハッシュコードは同じである可能性があります。これは、オブジェクトを作成するときに、Springが最初にキャッシュされたシングルトンプール(デフォルトはシングルトン、またはシングルトンプールとして理解できる)から取得するためです(キャッシュされたシングルトンプールからは取得しません)。それが解決策であるかどうかを知る循環依存の問題)初めて、実際のシングルトンプールからそれを取得します(Beanのライフサイクルコールチェーンはそのようなステップです)

能力の問題は後でしか修正できないので、お役に立てば幸いです。春のソースコードが醜いです。証拠がないため、オンラインの説明が正しいかどうかわかりません(オンラインの投稿が乱雑です。正しいものを見つけたい。見つけるのが難しい)。

おすすめ

転載: blog.csdn.net/qq_38108719/article/details/100592018