シーン:
- ビジネス処理を容易にするパッケージツール
- 春に管理されるBeanは、ツールクラスで呼び出す必要があります
- テスト呼び出しは、nullポインタ例外の問題を報告します
予備ツールコード:
@Component public class ScriptExecuteContent { @Autowired private static SignRepository signRepository; public static String checkSign(String certNo, String acctNo, String instCode) { Sign sign = signRepository.findByCertNoAndAcctNoAndInstCode(certNo, acctNo, instCode); if (null != sign && StringUtils.equals(sign.getStatus(), StatusEnum.SUCCESS.code()) && DateUtil.getCurrentDate().before(sign.getExpireTime())) { return "1"; } else { return "0"; } } }
コードはまばゆいばかりで問題はありませんが、ここに挿入されたsignRepositoryがnullであるため、null例外で実行されます。これは静的メソッドがクラスに属し、通常のメソッドがオブジェクトに属しているためです。Springインジェクションはコンテナでインスタンス化されます。変数、および静的はオブジェクトよりも優先して存在するため、静的メソッドに直接注入された静的変数は実際にはnullです。
考え:
- それでもSpringBeanのライフサイクルの問題
- そして、ロードの順序:コンストラクター(構築メソッド)-> @Autowired(依存性注入)-> @PostConstruct(アノテーション付きメソッド)の問題
Spring Beanのライフサイクル:
インスタンス化とプロパティの割り当ては、コンストラクターとセッターのメソッドの挿入に対応します。初期化と破棄は、ユーザーがカスタマイズおよび拡張できる2つの段階です。
- インスタンス化
- 属性の割り当てPopulate
- 初期化
- 破壊
初期化==> Beanオブジェクト変換の4つのメソッド:
破壊フェーズを呼び出すタイミング:
- 単一インスタンス:コンテナが閉じられたとき
- マルチインスタンス:コンテナはこのBeanを管理せず、その破棄メソッドを呼び出しません
解決策1:
@Autowiredはコンストラクターで使用されます
@Autowiredアノテーションは、クラスメンバーの変数、メソッド、およびコンストラクターにアノテーションを付けて、自動アセンブリの作業を完了することができることを知っています。この方法は、コンストラクターで@Autowiredを使用することです。
@Component public class ScriptExecuteContent { private static SignRepository signRepository; @Autowired public ScriptExecuteContent(SignRepository signRepository) { ScriptExecuteContent.signRepository = signRepository; } public static String checkSign(String certNo, String acctNo, String instCode) { Sign sign = signRepository.findByCertNoAndAcctNoAndInstCode(certNo, acctNo, instCode); if (null != sign && StringUtils.equals(sign.getStatus(), StatusEnum.SUCCESS.code()) && DateUtil.getCurrentDate().before(sign.getExpireTime())) { return "1"; } else { return "0"; } } }
解決策2:
@PostConstructアノテーションを使用する
- Java EE5仕様から、サーブレットのライフサイクルに影響を与える2つのアノテーション、@ PostConstructと@PreDestroyがサーブレットに追加されました。
- Javaでのこのアノテーションの説明:@PostConstructこのアノテーションはjavax.annotationパッケージの下にあり、非静的void()メソッドを装飾するために使用されます。
- @PostConstructによって変更されたメソッドは、サーバーがサーブレットをロードするときに実行され、サーバーによって1回だけ実行されます。
- @PostConstructによって変更されたメソッドは、コンストラクターの後、init()メソッドの前に実行されます。
- @PreDestroy()メソッドは、destroy()メソッドの実行後に実行されます
- @PostConstructアノテーションルール:インターセプターの特別な場合を除いて、他の場合にはパラメーターは許可されません。そうでない場合、Spring FrameworkはIllegalStateExceptionを報告します。戻り値が無効の場合、実際には戻り値を持つことができますが、少なくともそうではありません。エラーを報告します。無視されるだけです。
- 通常、Springフレームワークの@PostConstructアノテーションメソッドを使用して、Bean初期化全体でのアノテーションメソッドの実行順序にアノテーションを付けます。コンストラクター(構築メソッド)-> @Autowired(依存性注入)-> @PostConstruct(アノテーション付きメソッド)
@Component public class ScriptExecuteContent { @Autowired private SignRepository signRepository; private static ScriptExecuteContent scriptExecuteContent; @PostConstruct public void update() { scriptExecuteContent = this; scriptExecuteContent.signRepository = this.signRepository; } public static String checkSign(String certNo, String acctNo, String instCode) { Sign sign = scriptExecuteContent.signRepository.findByCertNoAndAcctNoAndInstCode(certNo, acctNo, instCode); if (null != sign && StringUtils.equals(sign.getStatus(), StatusEnum.SUCCESS.code()) && DateUtil.getCurrentDate().before(sign.getExpireTime())) { return "1"; } else { return "0"; } } }
例2:
@Component public class StaticBook { private static String url; @Value("${test.str}") private String str; @PostConstruct public void update() { this.url = this.str; } public static BookTestTemp getValue(){ return new BookTestTemp(1, "bookName", "123", url); } }