Longxingyoufengは、Beanオブジェクトの初期化と破棄のメソッドを実装するために仮想マシンにフックを登録します。

Longxingyoufengは、Beanオブジェクトの初期化と破棄のメソッドを実装するために仮想マシンにフックを登録します。

[[407482]]

目次

  • 1. はじめに
  • II.目的
  • 3. デザイン
  • 4. 実装
    • 1. プロジェクト構造
    • 2. 初期化メソッドと破棄メソッドのインターフェースを定義する
    • 3. Beanプロパティ定義に初期化と破棄を追加
    • 4. Beanオブジェクトの初期化メソッドを実行する
    • 5. 破棄メソッドアダプタを定義する(インターフェースと構成)
    • 6. Bean作成時に破棄メソッドオブジェクトを登録する
    • 7. 仮想マシンはフック登録を閉じ、破棄メソッドを呼び出す
  • 5. テスト
    • 1. 事前に準備する
    • 2. 設定ファイル
    • 3. ユニットテスト
  • VI.結論
  • 7. シリーズのおすすめ

1. はじめに

コードを存続させる方法はありますか?

[[407483]]

誰もがプロダクトマネージャーであると言う人もいますが、誰もがプログラマーになれることをご存知ですか?同様に:

  • プログラミングとは、プロパティを定義し、メソッドを作成し、呼び出して表示することです。
  • Java と PHP は男性と女性のようなものです。前者は構造化されたモジュールを重視し、後者は好きな色を重視します。
  • 丁寧に書きますが、書式を省略しないでください
  • 製品との最初の接点となる 3 つの宝物: レンガ、シャベル、包丁。それぞれ、役に立つ、使える、使いやすいことが保証されています。
  • 1行のコードから1トンのコードまで、開発はますます困難になり、障壁はますます高くなっています。

実際、コードの書き方を学ぶことは難しくありませんが、良いコードを書くことを学ぶことは困難です。読みやすさの観点から、コードには正確な名前と明確なコメントが必要です。使いやすさの観点から、外部サービスの呼び出しを簡素化するために、コードをデザイン パターンでパッケージ化する必要があります。拡張性の観点から、コードには適切なビジネスおよび機能実装の階層化が必要です。読みやすさ、使いやすさ、拡張のしやすさ、コーディング標準の強化などの制約の下、開発が完了してリリースされた後の配信結果は、高可用性、高パフォーマンス、高同時実行性などの要件も満たす必要があります。同時に、既存のプロジェクトのプロダクトマネージャーから新たな要求も受けることになります。

何をするか?レンガを積んでいるのは分かるけど、どの豚小屋を建てているのか分からないよ!

コーディングしているレンガが豚小屋を建てるためのものであったとしても、豚の数が増えるため、エリアを拡張し、水槽を交換し、餌を追加する必要があります。したがって、コードの作成が完了した後に追加の要件が発生しないことを保証する方法はありません。では、新しい要件によって、元の完璧にカプセル化された 500 行の ifelse が破壊されたらどうなるでしょうか?取り壊して再建すべきでしょうか?

兄弟よ、コードのための逃げ道を残しておいてくれ!コードでは定義済みのインターフェースを使用していますか? インターフェースはインターフェースを継承していますか? インターフェースは抽象クラスによって実装されていますか? クラスによって継承されたクラスはインターフェース メソッドを実装していますか?これらの操作は、プログラム ロジックを階層化、パーティション化、ブロック化し、コア ロジック レイヤーとビジネス カプセル化レイヤーを分離するためのものです。ビジネスに変更があった場合、ビジネス レイヤーでのアセンブリを完了するだけでよく、基盤となるコア ロジック サービスを頻繁に変更する必要はありません。追加されるインターフェースもよりアトミックであり、ビジネス セマンティクスを持ちません。したがって、この実装方法はコードに抜け道を残すことができます。それでもまだ理解できない場合は、デザイン パターンの適用プラクティスが多数含まれている「Relearning Java Design Patterns」と「Hand-held Spring」をお読みください。

II.目的

私たちのクラスによって作成された Bean オブジェクトが管理のために Spring コンテナに引き渡されると、このクラス オブジェクトにさらに多くの使用機能が与えられます。前の章で、インスタンス化前に登録された Bean 定義のプロパティ情報を変更する機能と、インスタンス化中の前処理と後処理をクラス オブジェクトに追加したのと同様に、これらの追加機能を実装することで、既存のプロジェクト内のクラス オブジェクトに対して対応する拡張処理を実行できるようになります。

さらに、Bean 初期化プロセス中にいくつかの操作を実行することも考えています。たとえば、データのロードと実行、登録センターへの接続による RPC インターフェイスの公開、Web プログラムを閉じる際のリンクの切断やメモリの破棄などの操作の実行に役立ちます。 Spring がない場合でも、コンストラクター、静的メソッド、手動呼び出しを通じて実現できますが、このアプローチは、すべての操作を Spring コンテナーに任せて管理するほど優れたものではありません。したがって、spring.xml には次の操作が表示されます。

ユーザーが XML で初期化メソッドと破棄メソッドを設定できること、または Spring を使用するときに使用する InitializingBean や DisposableBean インターフェースなどの実装クラスを通じて処理できることを満たす必要があります。 - 実は、初期化操作をアノテーションで処理する方法も存在しますが、アノテーションのロジックはまだ実装されておらず、そのような機能は今後改善される予定です。

3. デザイン

Spring のような巨大なフレームワークに直面すると、公開されたインターフェース定義や XML 構成、および実行される一連の拡張操作により、Spring フレームワークは非常に神秘的に見えます。実際、Bean コンテナの初期化中に追加されるこのような追加の処理操作は、定義されたインターフェース メソッドまたはリフレクション呼び出しクラスの XML で構成されたメソッドを事前に実行するだけです。最終的には、インターフェース定義に従って実装するだけで、Spring コンテナが処理中にそれを呼び出します。全体的な設計構造は次のとおりです。

  • spring.xml 構成に init-method および destroy-method アノテーションを追加します。構成ファイルの読み込みプロセス中に、BeanDefinition プロパティで注釈構成を定義します。このように、initializeBean 初期化操作プロジェクトでは、Bean 定義プロパティに設定されたメソッド情報をリフレクションを通じて呼び出すことができます。また、インターフェース実装の場合は、Bean オブジェクト ((InitializingBean) bean).afterPropertiesSet() を介して、対応するインターフェースで定義されたメソッドを直接呼び出すことができ、2 つのメソッドは同じ効果を実現します。
  • 初期化中に実行される操作に加えて、destroy-method および DisposableBean インターフェイスの定義により、Bean オブジェクトが初期化されるときに、破棄メソッド情報が DefaultSingletonBeanRegistry クラスの disposableBeans プロパティに登録されます。これは、その後の統合操作のためです。リフレクション呼び出しと直接インターフェース呼び出しは 2 つの異なる方法であるため、ここではアダプターの使用に関するセクションもあります。そのため、梱包にはアダプターを使用する必要があります。次のコードの説明では、DisposableBeanAdapter の特定の実装を参照してください。仮想マシンがシャットダウンを実行する前に破棄メソッドを実行する必要があるため、ここでは次のような登録フック操作が必要です: Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("close!")));このコードでテストを実行することもできますし、ApplicationContext.close メソッドを手動で呼び出してコンテナーを閉じることもできます。

4. 実装

1. プロジェクト構造

  1. 小さな春のステップ07
  2. └── 出典
  3. ├── メイン
  4. │ └── ジャワ
  5. │ └── cn.bugstack.springframework
  6. │ ├── 豆
  7. │ │ ├── 工場
  8. │ │ │ ├── 工場
  9. │ │ │ │ §── AutowireCapableBeanFactory.java
  10. │ │ │ │ §── BeanDefinition.java
  11. │ │ │ │ §── BeanFactoryPostProcessor.java
  12. │ │ │ │ §── BeanPostProcessor.java
  13. │ │ │ │ §── BeanReference.java
  14. │ │ │ │ §── ConfigurableBeanFactory.java
  15. │ │ │ │ └─ SingletonBeanRegistry.java
  16. │ │ │ ├── サポート
  17. │ │ │ │ §── AbstractAutowireCapableBeanFactory.java
  18. │ │ │ │ §── AbstractBeanDefinitionReader.java
  19. │ │ │ │ §── AbstractBeanFactory.java
  20. │ │ │ │ §── BeanDefinitionReader.java
  21. │ │ │ │ §── BeanDefinitionRegistry.java
  22. │ │ │ │ §── CglibSubclassingInstantiationStrategy.java
  23. │ │ │ │ §── DefaultListableBeanFactory.java
  24. │ │ │ │ §── DefaultSingletonBeanRegistry.java
  25. │ │ │ │ §── DisposableBeanAdapter.java
  26. │ │ │ │ §── InstantiationStrategy.java
  27. │ │ │ │ └─ SimpleInstantiationStrategy.java
  28. │ │ │ ├── サポート
  29. │ │ │ │ └─ XmlBeanDefinitionReader.java
  30. │ │ │ §── BeanFactory.java
  31. │ │ │ §── ConfigurableListableBeanFactory.java
  32. │ │ │ §── DisposableBean.java
  33. │ │ │ §── HierarchicalBeanFactory.java
  34. │ │ │ §──Bean.java の初期化
  35. │ │ │ └── ListableBeanFactory.java
  36. │ │ §── BeansException.java
  37. │ │ §── PropertyValue.java
  38. │ │ └─ PropertyValues.java
  39. │ ├── コンテキスト
  40. │ │ ├── サポート
  41. │ │ │ §── AbstractApplicationContext.java
  42. │ │ │ §── AbstractRefreshableApplicationContext.java
  43. │ │ │ §── AbstractXmlApplicationContext.java
  44. │ │ │ └─ ClassPathXmlApplicationContext.java
  45. │ │ §── ApplicationContext.java
  46. │ │ └─ ConfigurableApplicationContext.java
  47. │ ├──core.io
  48. │ │ §── ClassPathResource.java
  49. │ │ §── DefaultResourceLoader.java
  50. │ │ §── FileSystemResource.java
  51. │ │ §── Resource.java
  52. │ │ §── ResourceLoader.java
  53. │ │ └─ UrlResource.java
  54. │ └── ユーティリティ
  55. │ └── クラスユーティリティ.java
  56. └── テスト
  57. └── ジャワ
  58. └── cn.bugstack.springframework.test
  59. ├── 豆
  60. │ ├── UserDao.java
  61. │ ━─ UserService.java
  62. └── APIテスト.java

プロジェクトのソースコード: 公開アカウント「bugstack wormhole stack」、返信: Spring コラム、完全なソースコードを入手

SpringアプリケーションコンテキストとBeanオブジェクト拡張メカニズム間のクラス関係を図8-4に示す。

図8-4

  • 上記のクラス ダイアグラム全体の構造は、新しく追加された Bean のインスタンス化プロセスにおける初期化メソッドと破棄メソッドを説明しています。
  • 初期化と破棄、XML 構成とインターフェース定義の 2 つの方法を実装しているため、InitializingBean と DisposableBean の両方が存在し、spring.xml 構成情報を BeanDefinition にロードするために XmlBeanDefinitionReader が必要になります。
  • さらに、ConfigurableBeanFactory インターフェースは destroySingletons 破棄メソッドを定義し、AbstractBeanFactory によって継承された親クラス DefaultSingletonBeanRegistry は ConfigurableBeanFactory インターフェースで定義された destroySingletons メソッドを実装します。この種の設計は多くのプログラマーには使用されないかもしれません。インターフェースを実装する人は、インターフェースの実装操作を継承した親クラスに引き渡すのではなく、実装クラスを完成させる必要があります。これは非常に興味深いことであり、階層化されたサービスを分離するための優れた設計方法です。
  • 最後の部分では、仮想マシンがシャットダウンされる前に破棄操作が実行されることを確認するために、仮想マシンにフックを登録します。 Runtime.getRuntime().addShutdownHook(新しい Thread(() -> System.out.println("close!")));

2. 初期化メソッドと破棄メソッドのインターフェースを定義する

cn.bugstack.springframework.beans.factory.InitializingBean

  1. パブリックインターフェースInitializingBean {
  2.  
  3. /**
  4. * Beanは属性入力の呼び出しを処理します
  5. *
  6. * @例外をスローします
  7. */
  8. void afterPropertiesSet() は例外をスローします。
  9.  
  10. }

cn.bugstack.springframework.beans.factory.DisposableBean

  1. パブリックインターフェースDisposableBean {
  2.  
  3. void destroy() は例外をスローします。
  4.  
  5. }
  • InitializingBean と DisposableBean は、よく使用される 2 つのインターフェース メソッドです。 Spring と組み合わせて実装する必要がある一部のコンポーネントでは、これらの 2 つのメソッドが、パラメータの初期化と破棄の操作を実行するためによく使用されます。たとえば、インターフェースの公開、データベース データの読み取り、構成ファイルの読み込みなどです。

3. Beanプロパティ定義に初期化と破棄を追加

cn.bugstack.springframework.beans.factory.config.Bean定義

  1. パブリッククラスBeanDefinition {
  2.  
  3. プライベートクラス beanClass;
  4.  
  5. プライベートPropertyValues ​​propertyValues;
  6.  
  7. プライベート文字列 initMethodName;
  8.      
  9. プライベート文字列destroyMethodName;
  10.      
  11. // ...取得/設定 
  12. }
  • BeanDefinition に 2 つの新しい属性 initMethodName と destroyMethodName が追加されました。これら 2 つの属性は、spring.xml で構成された Bean オブジェクトで init-method="initDataMethod" destroy-method="destroyDataMethod" 操作を構成するためのものです。インターフェースを実装した場合の最終的な効果は同じです。唯一の違いは、一方がインターフェース メソッドへの直接呼び出しであり、もう一方が構成ファイルで読み取られたメソッドへのリフレクション呼び出しである点です。

4. Beanオブジェクトの初期化メソッドを実行する

cn.bugstack.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

  1. パブリック抽象クラスAbstractAutowireCapableBeanFactoryはAbstractBeanFactoryを拡張し、AutowireCapableBeanFactoryを実装します。
  2.  
  3. プライベートインスタンス化戦略インスタンス化戦略 = 新しい CglibSubclassingInstantiationStrategy();
  4.  
  5. @オーバーライド
  6. 保護されたオブジェクトcreateBean(String beanName, BeanDefinition beanDefinition, Object[] args)はBeansExceptionをスローします{
  7. オブジェクト bean = null ;
  8. 試す {
  9. bean = createBeanInstance(beanDefinition、beanName、args);
  10. // Beanの属性を入力します
  11. プロパティ値を適用します(beanName、bean、beanDefinition);
  12. // Bean の初期化メソッドと BeanPostProcessor の前処理メソッドと後処理メソッドを実行します
  13. bean =InitializeBean(beanName, bean, beanDefinition);
  14. } キャッチ (例外 e) {
  15. throw new BeansException( "Bean のインスタンス化に失敗しました" , e);
  16. }
  17.  
  18. // ...
  19.  
  20. シングルトンを追加します(beanName、bean);
  21. Beanを返します
  22. }
  23.  
  24. プライベートオブジェクトinitializeBean(String beanName, Object bean, BeanDefinition beanDefinition) {
  25. // 1. 処理前にBeanPostProcessorを実行する
  26. オブジェクト wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
  27.  
  28. //Beanオブジェクトの初期化メソッドを実行する
  29. 試す {
  30. 初期化メソッドを呼び出します(beanName、wrappedBean、beanDefinition);
  31. } キャッチ (例外 e) {
  32. throw new BeansException( "bean[" + beanName + "]のinitメソッドの呼び出しに失敗しました" , e);
  33. }
  34.  
  35. // 2. BeanPostProcessorを実行する処理
  36. wrapBean に、beanPostProcessorsAfterInitialization を適用します。
  37. wrapBeanを返します
  38. }
  39.  
  40. private void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) 例外をスローします {
  41. // 1. InitializingBeanインターフェースを実装する
  42. if (beanインスタンスInitializingBean) {
  43. ((InitializingBean) bean).afterPropertiesSet();
  44. }
  45.  
  46. // 2. 設定情報 init-method {判断は二次実行破壊を避ける}
  47. 文字列 initMethodName = beanDefinition.getInitMethodName();
  48. StrUtil.isNotEmpty(initMethodName) の場合 {
  49. メソッド initMethod = beanDefinition.getBeanClass().getMethod(initMethodName);
  50. if ( null == initMethod) {
  51. throw new BeansException( "'" + beanName + "'" という名前の Bean に '" + initMethodName + "'" という名前の init メソッドが見つかりませんでした。" );
  52. }
  53. initMethod.invoke(bean);
  54. }
  55. }
  56.  
  57. }
  • 抽象クラス AbstractAutowireCapableBeanFactory の createBean メソッドは、Bean オブジェクトを作成するために使用されます。このメソッドでは、以前に BeanFactoryPostProcessor および BeanPostProcessor 操作を拡張しました。ここでは、Bean オブジェクトの初期化メソッドを実行する処理アクションの改善を続けます。
  • メソッドinvokeInitMethodsには、InitializingBeanインターフェースを実装し、afterPropertiesSetメソッドを処理する操作を実行する2つの主要な部分があります。もう 1 つは、構成情報 init-method が存在するかどうかを判断し、リフレクション呼び出し initMethod.invoke(bean) を実行することです。どちらの方法も、Bean オブジェクトの初期化プロセス中に Bean オブジェクトに初期化操作をロードするために使用でき、ユーザーは必要な追加アクションを追加できます。

5. 破棄メソッドアダプタを定義する(インターフェースと構成)

cn.bugstack.springframework.beans.factory.support.DisposableBeanAdapter

  1. パブリッククラスDisposableBeanAdapterはDisposableBeanを実装します{
  2.  
  3. プライベート最終オブジェクト bean;
  4. プライベート最終文字列 beanName;
  5. プライベート文字列destroyMethodName;
  6.  
  7. パブリックDisposableBeanAdapter(オブジェクト bean、文字列 beanName、BeanDefinition beanDefinition) {
  8. this.bean = ビーン;
  9. this.beanName = beanName;
  10. this.destroyMethodName = beanDefinition.getDestroyMethodName();
  11. }
  12.  
  13. @オーバーライド
  14. パブリックvoid destroy() 例外をスローします {
  15. // 1. DisposableBeanインターフェースを実装する
  16. if (DisposableBeanのBeanインスタンス) {
  17. DisposableBean を破棄します。
  18. }
  19.  
  20. // 2. 設定情報 destroy-method {判定は破棄の二次実行を避ける}
  21. if (StrUtil.isNotEmpty(destroyMethodName) && !(bean instanceof DisposableBean && "destroy" .equals(this.destroyMethodName))) {
  22. メソッド destroyMethod = bean.getClass().getMethod(destroyMethodName);
  23. if ( null == 破棄メソッド) {
  24. throw new BeansException( "'" + beanName + "'" という名前の Bean に '" + destroyMethodName + "' という名前の destroy メソッドが見つかりませんでした" );
  25. }
  26. destroyMethod.invoke(bean);
  27. }
  28.          
  29. }
  30.  
  31. }
  • メソッドを破棄する方法が 2 つ以上あるため、なぜここにアダプター クラスがあるのか​​疑問に思うかもしれません。現在、DisposableBean インターフェースを実装する方法と、destroy-method 情報を構成する方法の 2 つがあります。これら 2 つのメソッドの破棄アクションは、仮想マシン フックを登録した後、仮想マシンがシャットダウンされる前に、AbstractApplicationContext によって実行されます。
  • したがって、オブジェクトを破棄するときには、それらの型を破棄するメソッドに注意を払う必要はありません。破壊のための統一されたインターフェースを持つことを望んでいます。そのため、統一された処理を行うためのアダプタ クラスを追加します。

6. Bean作成時に破棄メソッドオブジェクトを登録する

cn.bugstack.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

  1. パブリック抽象クラスAbstractAutowireCapableBeanFactoryはAbstractBeanFactoryを拡張し、AutowireCapableBeanFactoryを実装します。
  2.  
  3. プライベートインスタンス化戦略インスタンス化戦略 = 新しい CglibSubclassingInstantiationStrategy();
  4.  
  5. @オーバーライド
  6. 保護されたオブジェクトcreateBean(String beanName, BeanDefinition beanDefinition, Object[] args)はBeansExceptionをスローします{
  7. オブジェクト bean = null ;
  8. 試す {
  9. bean = createBeanInstance(beanDefinition、beanName、args);
  10. // Bean属性を入力する
  11. プロパティ値を適用します(beanName、bean、beanDefinition);
  12. // Bean の初期化メソッドと BeanPostProcessor の前処理メソッドと後処理メソッドを実行します
  13. bean =InitializeBean(beanName, bean, beanDefinition);
  14. } キャッチ (例外 e) {
  15. throw new BeansException( "Bean のインスタンス化に失敗しました" , e);
  16. }
  17.  
  18. //DisposableBeanインターフェースを実装するBeanオブジェクトを登録する
  19. 必要に応じてDisposableBeanを登録します(beanName、bean、beanDefinition);
  20.  
  21. シングルトンを追加します(beanName、bean);
  22. Beanを返します
  23. }
  24.  
  25. 保護された void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition) {
  26. if (bean インスタンスが DisposableBean の場合 || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())) {
  27. DisposableBean を登録します (beanName、新しい DisposableBeanAdapter (bean、beanName、beanDefinition));
  28. }
  29. }
  30.  
  31. }

Bean オブジェクトのインスタンスを作成するときは、破棄アクションが実行されるときに後で呼び出せるように、破棄メソッドを保存する必要があります。

次に、この破棄メソッドの特定のメソッド情報が、DefaultSingletonBeanRegistryに新しく追加されたマップに登録されます。

破棄メソッドを登録すると、インターフェースの種類と構成の種類に基づいて統一された処理のために、DisposableBeanAdapter 破棄アダプタ クラスに一律に引き渡されます。インターフェースを実装するクラスは、instanceofによって判断されるか、インターフェースメソッドを呼び出すように強制される。

7. 仮想マシンはフック登録を閉じ、破棄メソッドを呼び出す

cn.bugstack.springframework.context.ConfigurableApplicationContext

  1. パブリックインターフェースConfigurableApplicationContextはApplicationContextを拡張します{
  2.  
  3. void refresh() は BeansException をスローします。
  4.  
  5. シャットダウンフックを登録します。
  6.  
  7. voidを閉じる();
  8.  
  9. }
  • まず、仮想マシン フックを登録するための registerShutdownHook メソッドと、シャットダウンを手動で実行するための close メソッドを ConfigurableApplicationContext インターフェイスで定義する必要があります。

cn.bugstack.springframework.context.support.AbstractApplicationContext

  1. パブリック抽象クラスAbstractApplicationContextはDefaultResourceLoaderを拡張し、ConfigurableApplicationContextを実装します{
  2.  
  3. // ...
  4.  
  5. @オーバーライド
  6. パブリックvoid registerShutdownHook() {
  7. Runtime.getRuntime().addShutdownHook(新しいスレッド(this:: close ));
  8. }
  9.  
  10. @オーバーライド
  11. パブリックボイドクローズ(){
  12. getBeanFactory() のシングルトンを破棄します。
  13. }
  14.  
  15. }
  • これは主に、登録フックとシャットダウン メソッドの実装を反映しています。上記の Runtime.getRuntime().addShutdownHook を検証してみてください。また、サーバーの障害の監視やスタンバイ マシンの起動操作の実行など、一部のミドルウェアや監視システムの設計にも使用できます。

5. テスト

1. 事前に準備する

cn.bugstack.springframework.test.bean.UserDao

  1. パブリッククラスUserDao{
  2.  
  3. プライベート静的Map<String, String> hashMap = new HashMap<>();
  4.  
  5. パブリックvoid initDataMethod(){
  6. System.out.println ( "実行: init-method" ) ;
  7. hashMap.put( "10001" , "リトルブラザーフー" );
  8. hashMap.put( "10002" , "コップ8杯の水" );
  9. hashMap.put( "10003" , "阿毛" );
  10. }
  11.  
  12. パブリックvoid destroyDataMethod(){
  13. システム。 out .println( "実行: destroy-method" );
  14. ハッシュマップをクリアします。
  15. }
  16.  
  17. パブリック文字列クエリユーザー名(文字列uId) {
  18. hashMap.get(uId)を返します
  19. }
  20.  
  21. }

cn.bugstack.springframework.test.bean.UserService

  1. パブリッククラスUserServiceはInitializingBean、DisposableBeanを実装します。
  2.  
  3. プライベート文字列 uId;
  4. 民間のストリング会社。
  5. プライベート文字列の場所;
  6. プライベート UserDao userDao;
  7.  
  8. @オーバーライド
  9. パブリックvoid destroy() 例外をスローします {
  10. System.out.println ( "実行: UserService.destroy" ) ;
  11. }
  12.  
  13. @オーバーライド
  14. パブリックvoid afterPropertiesSet() は例外をスローします {
  15. System.out.println ( "実行: UserService.afterPropertiesSet" ) ;
  16. }
  17.  
  18. // ...取得/設定 
  19. }

UserDao は、データを初期化するために静的ブロックを使用する以前の方法を変更し、代わりに、処理用に initDataMethod と destroyDataMethod という 2 つのより洗練された操作メソッドを提供します。

UserService は、InitializingBean と DisposableBean の 2 つのメソッド、destroy() と afterPropertiesSet() を実装して、対応する初期化メソッドと破棄メソッドのアクションを処理します。 afterPropertiesSetはプロパティが設定された後に実行される適切なメソッド名です。

2. 設定ファイル

基本構成、BeanFactoryPostProcessorなし、BeanPostProcessor、実装クラス

  1. <?xml バージョン = "1.0"エンコーディング = "UTF-8" ?>
  2. <豆>
  3.  
  4. <bean id= "userDao"クラス= "cn.bugstack.springframework.test.bean.UserDao" init-method= "initDataMethod" destroy-method= "destroyDataMethod" />
  5.  
  6. <bean id= "userService"クラス= "cn.bugstack.springframework.test.bean.UserService" >
  7. <プロパティ= "uId"値 = "10001" />
  8. <プロパティ= "company"値 = "Tencent" />
  9. <プロパティ= "場所"値 = "深セン" />
  10. <プロパティ= "userDao" ref = "userDao" />
  11. </bean>
  12.  
  13. </豆>

  • 構成ファイルは主に、init-method="initDataMethod" と destroy-method="destroyDataMethod" の 2 つの構成を追加します。ソース コードを調査すると、これらの 2 つの構成は BeanDefinition 定義クラスに追加され、DefaultListableBeanFactory クラスの beanDefinitionMap 属性に書き込まれることがわかります。

3. ユニットテスト

  1. @テスト
  2. パブリックボイドtest_xml() {
  3. // 1. BeanFactoryを初期化する
  4. ClassPathXmlApplicationContext アプリケーション コンテキスト = 新しい ClassPathXmlApplicationContext( "classpath:spring.xml" );
  5. アプリケーションコンテキストを登録してシャットダウンフックを呼び出します。
  6.  
  7. // 2. メソッド呼び出しでBeanオブジェクトを取得する
  8. UserService userService = applicationContext.getBean( "userService" 、 UserService.class);
  9. 文字列結果 = userService.queryUserInfo();
  10. システム。 out .println( "テスト結果: " + result);
  11. }
  • フックを登録するための新しいアクションがテスト メソッドに追加されました。アプリケーションコンテキストを登録してシャットダウンフックを呼び出します。

テスト結果

実行: init-method

実行: UserService.afterPropertiesSet

テスト結果: 小富貴、テンセント、深セン

実行: UserService.destroy

実行: destroy-method

プロセスは終了コード 0 で終了しました

  • テスト結果から、新しく追加した初期化メソッドと破棄メソッドが期待どおりの結果を出力できることがわかります。

VI.結論

  • この記事では主に、InitializingBean、DisposableBean を実装するインターフェース定義を使用し、spring.xml で init-method="initDataMethod" destroy-method="destroyDataMethod" を構成して初期化メソッドを完了し、AbstractApplicationContext を使用して破棄アクションを処理する、AbstractAutowireCapableBeanFactory での初期化と破棄の具体的な実装プロセスを完了します。
  • この記事の実装内容を通じて、現在の Spring フレームワークの Bean に対する操作はますます完璧になり、スケーラビリティが継続的に向上していることがわかります。 Bean の登録が完了してインスタンス化される前に BeanFactoryPostProcessor 操作を実行したり、Bean のインスタンス化プロセス中に前処理操作と後処理操作を実行したりできます。これで、Bean の初期化メソッドと破棄メソッドを実行できます。そのため、単純な Bean オブジェクトにさまざまな拡張機能が与えられています。
  • Spring フレームワークを学習し実践する過程では、インターフェースと抽象クラスの理解と使用に特別な注意を払う必要があります。これは、A が B を継承して C を実装し、C のインターフェース メソッドが A が継承した親クラス B によって実装されるという状況に遭遇したときに特に興味深いものです。また、通常のビジネス システムの開発で再利用して、いくつかの複雑な論理機能レイヤーを処理することもできるため、プログラムのスケーラビリティが向上し、保守が容易になります。

<<:  複数のクラスター内の Tekton パイプライン

>>:  Redisson 分散ロック ソースコード 1: 再入可能ロック

推薦する

Gラインクラウドコンピューティングシリーズ:フルスタッククラウド運用

導入G銀行の123+Nデジタルバンキング開発システムの基本技術プラットフォームのクラウドコンピューテ...

3人の男が営利目的で「伝説のプライベートサーバー」を立ち上げ、著作権侵害の疑い

楽山市の20代前半の若者3人が個人的にネットワークサーバーを設置し、人気のオンラインゲーム「Lege...

専門家の視点: エッジ コンピューティングの課題を克服するには?

エッジへの移行には、未成熟なエコシステムからリスク管理まで、さまざまな課題が伴います。これら 4 つ...

新しいサイトのインデックス作成が遅い問題を解決する4つの重要な解決策

最近、新しいウェブサイトを構築しました。すべての初心者ウェブマスターと同様に、毎日コンピュータの電源...

B2B ブランドマーケティングにどれだけのお金が浪費されてきたでしょうか?

B2Bブランド マーケティングは、特に中国では、常に恥ずかしい話題でした。恥ずかしいことに、当初は誰...

Canalys: 中国のクラウドコンピューティングインフラ支出は四半期で30億ドル近く

Canalys は本日、中国におけるクラウド コンピューティング インフラストラクチャ支出に関する最...

SEO最適化におけるマシュー効果

弊社のウェブマスターがインターネットプロモーションアウトソーシングのサービスを利用しているときに、最...

ウェブサイトの緊急事態: スペースを変更した後の 301 がウェブサイトのランキングに与える影響

私たちはウェブサイトのスペースの変更に十分な準備ができていなかったと言わざるを得ませんし、Baidu...

マーケティングコンテンツを台無しにする8つの方法

あなたは自分の努力を妨害していませんか?アン・ハンドリーマーケティングの無駄は非常に深刻です。評判を...

母の日に大手ブランドが送る優れたコピーライティング集

もうすぐ母の日がやってきます。大手ブランドのコピーライティングから学んでみましょう〜今週の日曜日、5...

Google と Google ランキングを最適化する方法の解釈

Google のランキングを最適化するにはどうすればいいですか? 1. タイトルにキーワードが表示さ...

中国初のITチャンネルメディア「コンピュータビジネスニュース」が運営停止

コンピュータビジネスニュースのホームページに残っているのは停止通知だけだ1月30日午前のニュースによ...

SEO最適化には、作業効率を向上させるための合理的な外部リンク最適化プロセスが必要です。

ウェブサイトの最適化で最も頭を悩ませるのは、外部リンクの構築です。「神」レベルの人でも、この「ゆっく...

主要な情報フロープラットフォームの実際のトラフィックはどの程度でしょうか?最新のデータを見ればわかります!チャンネル必須!

情報フローを作成する際に、最適化技術の他に最も注意すべきことはトラフィックです。交通量は多いですか?...

#BlackFridayPresale# cloudcone: ロサンゼルスの大型ハードドライブ VPS、年間 16 ドルから、最大 1T ハードドライブ/10T トラフィック

Cloudcone はすでに毎年恒例のブラックフライデーのプレセールを事前に開始しており、ロサンゼル...