注:新たな基本的考え方の概要は4月から5月に完成する予定である。
1. BeanPostProcessorの基礎知識のまとめ
BeanPostProcessor は、属性の検証、カスタム Bean の統合処理など、Bean のインスタンス化および初期化後に Bean インスタンスをカスタマイズするために使用される Bean レベルのプロセッサです。
BeanPostProcessor インターフェースには 2 つのメソッドが定義されています。
-
postProcessBeforeInitialization メソッドは、Bean 初期化コールバック (InitializingBean インターフェースの afterPropertiesSet メソッド、カスタム初期化メソッドなど) の前に、指定された Bean インスタンスに BeanPostProcessor を適用します。その戻り値は、Bean 自体またはそのラッパー クラスになります。
-
postProcessAfterInitialization メソッドは、Bean コールバック初期化メソッドの後に呼び出されます。
実装プロセス:登録~postProcessBeforeInitializationの実行~postProcessAfterInitializationの実行
Spring コンテナで Bean のインスタンス化、構成、その他の初期化メソッドを完了したい場合は、前後に独自のロジック処理を追加する必要があります。1 つ以上の BeanPostProcessor インターフェイス実装クラスを定義し、それらを Spring IoC コンテナに登録する必要があります。
Spring での Bean のインスタンス化プロセスの図:
知らせ:
1. インターフェースの両方のメソッドは受信 Bean を返す必要があり、null を返すことはできません。null が返された場合、getBean メソッドを通じてターゲットを取得できません。
2. BeanFactory と ApplicationContext は、Bean ポストプロセッサの扱いが少し異なります。ApplicationContext は、構成ファイルで BeanPostProcessor インターフェースを実装するすべての Bean を自動的に検出し、それらをポストプロセッサーとして登録し、コンテナーが Bean を作成するときにそれを呼び出します。 . 違いはありません。BeanFactory を使用して実装する場合、Bean ポストプロセッサーはコードを通じて明示的に登録する必要があります。登録メソッドは、IoC コンテナー継承システムの ConfigurableBeanFactory インターフェースで定義されます。
/**
* Add a new BeanPostProcessor that will get applied to beans created
* by this factory. To be invoked during factory configuration.
* <p>Note: Post-processors submitted here will be applied in the order of
* registration; any ordering semantics expressed through implementing the
* {@link org.springframework.core.Ordered} interface will be ignored. Note
* that autodetected post-processors (e.g. as beans in an ApplicationContext)
* will always be applied after programmatically registered ones.
* @param beanPostProcessor the post-processor to register
*/
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
また、BeanPostProcessor を遅延初期化としてマークしないでください。これを行うと、Spring コンテナーがそれらを登録せず、カスタム ロジックが適用されないためです。<beans /> 要素の定義で「default-lazy-init」属性を使用する場合は、各 BeanPostProcessor タグが「lazy-init="false"」であることを確認してください。
2. BeanPostProcessorの実用化に関する分析
Spring フレームワークには BeanPostProcessor インターフェースの実際的なアプリケーション シナリオが多数あります。いくつかの例を次に示します。
- プロパティの注入: BeanPostProcessor インターフェースを実装することにより、Bean がインスタンス化された後、初期化前に Bean プロパティのカスタム注入を実行できます。たとえば、BeanPostProcessor の postProcessBeforeInitialization メソッドで Bean のプロパティを変更または値を割り当てて、プロパティ注入のカスタマイズされた要件を実現できます。
- AOP 前処理: Bean がインスタンス化された後、初期化前に、BeanPostProcessor インターフェースを実装することで、Bean に対して AOP 関連の前処理を実行できます。たとえば、BeanPostProcessor の postProcessBeforeInitialization メソッドで Bean のプロキシ オブジェクトを動的に生成して、AOP アスペクト指向関数を実装できます。
- カスタマイズされた初期化ロジック: BeanPostProcessor インターフェースを実装することで、Bean の初期化フェーズ中に Bean のカスタマイズされた初期化ロジックを実装できます。たとえば、BeanPostProcessor の postProcessAfterInitialization メソッドで、データの初期化、リソースのロードなどの一部の初期化操作を実行できます。
- データ検証: BeanPostProcessor インターフェースを実装することで、Bean の初期化後に Bean 内のデータを検証できます。たとえば、BeanPostProcessor の postProcessAfterInitialization メソッドで Bean 内のデータを検証して、データの合法性と整合性を確認できます。
- リソースのリサイクル: BeanPostProcessor インターフェースを実装することで、Bean が破棄される前に Bean 内のリソースをリサイクルできます。たとえば、BeanPostProcessor の postProcessBeforeDestruction メソッドでリソースの解放やクローズなどの操作を実行して、リソースを適切に解放することができます。
BeanPostProcessor インターフェースを実装するときは、不要な副作用や潜在的な問題が発生しないように、Bean のライフサイクルを慎重に処理する必要があることに注意してください。BeanPostProcessor インターフェースを使用する場合は、本当に Bean をカスタマイズする必要があるかどうか、また特定のニーズに基づいて処理のタイミングと方法を慎重に検討する必要があります。
3. 応用例の表示
(1) 属性インジェクション
BeanPostProcessor インターフェースを実装すると、Bean がインスタンス化された後、初期化前に Bean プロパティのカスタム注入を実行できます。たとえば、BeanPostProcessor の postProcessBeforeInitialization メソッドで Bean のプロパティを変更または値を割り当てて、プロパティ注入のカスタマイズされた要件を実現できます。
MyBeanPostProcessor を定義して BeanPostProcessor インターフェースを実装し、その 2 つのメソッド postProcessBeforeInitialization および postProcessAfterInitialization をオーバーライドします。
postProcessBeforeInitialization メソッドでは、MyBean 型 Bean に対して属性のカスタム インジェクションが実行され、属性インジェクションのカスタマイズされた要件が実現されます (これは単なる例であり、実際のアプリケーションの処理ロジックはさらに複雑になる可能性があり、カスタマイズされた処理は次のとおりに実行されます)特定のニーズ。)
package org.zyf.javabasic.springextend.beanpostprocessorext;
import lombok.Data;
/**
* @author yanfengzhang
* @description
* @date 2023/4/16 23:54
*/
@Data
public class MyBean {
private String myProperty;
public void doSomething(){
System.out.println("MyBean.doSomething()执行,myProperty="+myProperty);
}
}
実際のアプリケーションでは、ビジネス ニーズに応じて、MyBean をビジネス ロジック実装クラス、データ アクセス オブジェクトなどのビジネス オブジェクトにすることができます。MyBean は単なるプレースホルダーであり、実際のビジネス ニーズやビジネス オブジェクトの命名規則に従って独自の Bean タイプを定義し、名前を付けることができます。実際のアプリケーションでは、MyBeanPostProcessor で対応する処理を実行するために、MyBean を実際に使用するビジネス オブジェクトのクラス名に置き換える必要があります。
構成例
このカスタム BeanPostProcessor を使用するには、Spring コンテナーに登録する必要があります。方法は 2 つあります。
設定ファイル経由
<!-- 配置文件中的注册方式 -->
<bean class="org.zyf.javabasic.springextend.beanpostprocessorext.MyBeanPostProcessor" />
Java を使用したクラスの構成
package org.zyf.javabasic.springextend.beanpostprocessorext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author yanfengzhang
* @description
* @date 2023/4/16 23:58
*/
@Configuration
public class MyAppConfig {
@Bean
public MyBeanPostProcessor myBeanPostProcessor() {
return new MyBeanPostProcessor();
}
}
コード表示
package org.zyf.javabasic.springextend.beanpostprocessorext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* @author yanfengzhang
* @description
* @date 2023/4/16 23:53
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 在 Bean 初始化前的处理逻辑
if (bean instanceof MyBean) {
MyBean myBean = (MyBean) bean;
// 对 MyBean 的属性进行自定义注入
myBean.setMyProperty("自定义属性");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// 在 Bean 初始化后的处理逻辑
return bean;
}
}
このように、Spring コンテナは、Bean をインスタンス化して初期化する前に、MyBeanPostProcessor の postProcessBeforeInitialization メソッドを呼び出して、プロパティ インジェクションのカスタム処理を実装します。MyBeanPostProcessor が Spring コンテナによって認識され、そのロジックが実行されるためには、Spring コンテナに Bean として登録される必要があることに注意してください。
私たちの確認コードは次のとおりです。
package org.zyf.javabasic;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.zyf.javabasic.springextend.beanpostprocessorext.MyBean;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* 描述:启动入口类
*
* @author yanfengzhang
* @date 2019-12-19 18:11
*/
@SpringBootApplication
@ComponentScan(basePackages = {"org.zyf.javabasic"})
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
@EnableSwagger2
public class ZYFApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(ZYFApplication.class, args);
// 使用 MyBean
MyBean myBean = context.getBean(MyBean.class);
myBean.doSomething(); // 调用 MyBean.doSomething() 方法
}
@Bean
public MyBean myBean(){
return new MyBean();
}
}
特定のリターンでは以下の表示に注意してください
(2) AOPの前処理
BeanPostProcessor インターフェースを実装することで、Bean がインスタンス化された後、初期化の前に、Bean に対して AOP 関連の前処理を実行できます。たとえば、BeanPostProcessor の postProcessBeforeInitialization メソッドで Bean のプロキシ オブジェクトを動的に生成して、AOP アスペクト指向関数を実装できます。
参考リンク:
1.春の実践シリーズ (3) - BeanPostProcessor の魔法の使い方_Qinghong Piaoyu のブログ - CSDN ブログ