JAVA-6-[Spring Framework] Bean のスコープとライフサイクル

春豆 1個

1、Spring有两种类型bean,一种普通bean,另外一种工厂bean(FactoryBean)2、普通bean:在配置文件中定义的bean类型就是返回的类型。
3、工厂bean:在配置文件中定义的bean类型可以和返回类型不一样。
第一步 创建类,让这个类作为工厂bean,实现接口FactoryBean
第二步 实现接口里面的方法,在实现的方法中定义返回的bean类型

1.1 Bean名称由来

Spring IoC コンテナが管理するオブジェクトは Bean と呼ばれ、Bean は Spring 設定ファイルの情報に従って作成されます。

Spring IoC コンテナは大きな工場と考えることができます。Bean は工場の製品に相当します。この大きな工場で Bean を生産および管理したい場合は、コンテナにどの Bean が必要か、およびコンポーネントの組み立て方法を伝える必要があります。豆。
1. JAVA という名前の由来
Java が Sun によって最初に発明されたとき、Java は Java ではなく、Oak (樫の木) と呼ばれていました。オークという名前は、Java の発明者の 1 人であるジェームズ ゴズリングのオフィスの外にある樫の木にちなんで命名されました。いかにカジュアルな気持ちで名付けたのかがわかります。
ここに画像の説明を挿入

残念ながら、Oak という名前がすでに他社によって商標登録されていることがすぐにわかり、別の名前を作成する必要がありました。どちらの名前が良いでしょうか?当時、彼らは長い間議論し、最終的にいくつかの候補名の中から「Java」という名前を選びました。

なぜ Java という名前を選んだのですか? これは著者がよく言及していることですが、西洋人は食べ物関連のコンテンツを名前に使うのが好きです。さらに、当時のこれらのプログラマーの脳回路は非常に奇妙でした。Java という名前は、オフィスのホットコーヒーに関連付けられていました。歴史的には、オランダがインドネシアを植民地化した 1696 年に、現在のインドネシアの首都ジャカルタでコーヒーの苗木が普及し始めました。その後、人々はインドネシアでコーヒーの苗木を必死で植え、ヨーロッパに供給しました。その後、インドネシアのジャワ島という島でコーヒーが豊かになりました。島で生産されるコーヒーの評判のため、ジャワという言葉はコーヒーを連想しやすいです。こうして、プログラミング言語 Java という名前が生まれました。

興味深いことに、この Java のネーミングにより、後に Java EE が名前を変更する際に、Jakarta EE という名前に変更されました。ジャカルタは現在インドネシアの首都です。そのため、インドネシアと血縁関係のないJavの創設者らは、インドネシアに関連した一連の名前を使用した。

また、この名前のせいで、Java に関連する多くのもので、NetBeans、Beans in Spring など、コーヒー豆に関連した名前が使用されています。
二、Beanの由来
ここに画像の説明を挿入

Bean は Spring フレームワークにおける非常に基本的な概念であり、Bean という言葉は英語で「豆」を意味します。Spring フレームワークでの Bean の実際の使用から見ると、この 2 つは互いに何の関係もないように見えますが、なぜこのような名前になったのでしょうか?
BeanはSpringフレームワークの基本単位を表します。Springフレームワークのプリセットオブジェクトのほとんどは一種の「Bean」です。データの各種処理もBean単位で行われ、ユーザー定義のデータもBean単位で構築する必要があります。処理される前に Bean に変換されます。

一方、Spring フレームワークでの実際の意味に従って Bean に名前を付ける場合は、「要素」や「ユニット」などの単語に基づいて名前を付ける必要があります。しかし問題は、コンピュータ関連分野において「要素」「ユニット」「原子」「コンポーネント」といった言葉が固有名詞になっているか、あるいは固有名詞となる可能性があることです。このネーミングだと「曖昧さ」が生じる可能性があります。衝突。

一方、西洋人は食べ物や飲み物にちなんだ名前を付けるのが好きです。ケータリングの基本食材とも言える「豆」。

1.2 Spring設定ファイル

Spring 構成ファイルは、XML ファイル形式とプロパティ ファイル形式の 2 つの形式をサポートしています。
(1) プロパティ設定ファイルは主にキーと値のキーと値のペアの形式で存在し、値を割り当てることのみが可能で、他の操作は実行できません。単純なプロパティの設定に適しています。

(2) XML 設定ファイルはツリー構造になっており、プロパティ ファイルよりも柔軟です。XML 構成ファイルの構造は明確ですが、内容は比較的複雑なので、大規模で複雑なプロジェクトに適しています。

1. 通常、Spring の設定ファイルは XML 形式を使用します

XML配置文件的根元素是<beans>,该元素包含了多个子元素<bean>。
每一个<bean>元素都定义了一个Bean,
并描述了该Bean如何被装配到Spring容器中。

2、Beans.xml ファイルの例

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean id="helloWorld123" class="net.biancheng.HelloWorld">
        <property name="message" value="Hello World! Testing" />
    </bean>
</beans>

ここに画像の説明を挿入

2 Bean スコープ

Spring で Bean を定義するときは、Bean のスコープのオプションを宣言する必要があります。たとえば、新しい Bean インスタンスが必要になるたびに Spring に強制的に作成させるには、Bean のスコープ プロパティをプロトタイプとして宣言する必要があります。同様に、Spring が必要になるたびに同じ Bean インスタンスを返すようにしたい場合は、Bean のスコープ プロパティをシングルトンとして宣言する必要があります。

Springフレームワークでは、シングルトン、プロトタイプ、リクエスト、セッション、グローバルセッションの5つのスコープをサポートしており、各スコープの説明は以下の通りです。

Web 対応の ApplicationContext を使用する場合は、そのうち 3 つが使用できることに注意してください。
ここに画像の説明を挿入

2.1 シングルトンスコープ

シングルトンはデフォルトのスコープです。つまり、Bean を定義するときにスコープ構成項目が指定されていない場合、Bean のスコープはデフォルトでシングルトンになります。
Bean のスコープがシングルトンの場合、Spring IoC コンテナには共有 Bean インスタンスが 1 つだけ存在し、ID が Bean 定義と一致する限り、Bean に対するすべてのリクエストは同じ Bean インスタンスのみを返します。

つまり、Bean 定義がシングルトン スコープに設定されている場合、Spring IoC コンテナは Bean 定義の唯一のインスタンスのみを作成します。

Singleton はシングルトン型、つまりコンテナ作成時に Bean オブジェクトも同時に自動的に作成され、使用するかどうかに関係なく存在し、毎回取得されるオブジェクトは同じオブジェクトです。Singleton スコープが Spring のデフォルトのスコープであることに注意してください。次のように、Bean 構成ファイルでスコープ プロパティをシングルトンに設定できます。

<!-- A bean definition with singleton scope -->
<bean id="..." class="..." scope="singleton">
    <!-- collaborators and configuration for this bean go here -->
</bean>

MainApp.java ファイル

package net.biancheng;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
    
    
    public static void main(String[] args) {
    
    
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        HelloWorld objA = (HelloWorld) context.getBean("helloWorld123");
        objA.setMessage("I am A");
        objA.getMessage();
        HelloWorld objB = (HelloWorld) context.getBean("helloWorld123");
        objB.getMessage();
    }
}

次の情報を出力します。

Your Message : I'm object A
Your Message : I'm object A

2.2 プロトタイプのスコープ

Bean のスコープが Prototype の場合、Bean 定義が複数のオブジェクト インスタンスに対応することを意味します。プロトタイプ スコープの Bean では、Bean が要求されるたびに (別の Bean に注入するか、プログラムでコンテナの getBean() メソッドを呼び出すことによって) 新しい Bean インスタンスが作成されます。

Prototypeはプロトタイプの型で、コンテナ作成時にはインスタンス化されず、Bean取得時にオブジェクトが作成され、毎回取得するオブジェクトは同じオブジェクトではありません。経験則として、ステートフル Bean にはプロトタイプ スコープを使用し、ステートレス Bean にはシングルトン スコープを使用する必要があります。

プロトタイプのスコープを定義するには、次のように、Bean 構成ファイルでスコープ プロパティをプロトタイプに設定します。

<!-- A bean definition with singleton scope -->
<bean id="..." class="..." scope="prototype">
   <!-- collaborators and configuration for this bean go here -->
</bean>

Beans.xml ファイル

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="helloWorld123" class="net.biancheng.HelloWorld" scope="prototype">
        <property name="message" value="Hello World! Testing" />
    </bean>

</beans>

出力は次のとおりです。

message : I am A
message : Hello World! Testing

3 Bean のライフサイクル

Bean がインスタンス化されるとき、使用可能な状態にするために初期化を実行する必要がある場合があります。同様に、Bean が不要になりコンテナから取り外される場合、何らかのクリーンアップが必要になる場合があります。

Bean のインスタンス化と破棄の間には依然としていくつかのアクティビティが発生しますが、今回は Bean の初期化と破棄中に必要な 2 つの重要なライフサイクル コールバック メソッドのみについて説明します。

Bean のインストールと破棄を定義するには、init-method または destroy-method パラメーターを使用して Bean を宣言するだけです。
init-method 属性は、Bean がインスタンス化されるときにすぐに呼び出されるメソッドを指定します。
destroy-method は、Bean がコンテナから削除された後にのみ呼び出すことができるメソッドを指定します。

Beanのライフサイクルは、Beanの定義 - Beanの初期化 - Beanの使用 - Beanの破棄 と表すことができます。

4.3.1 初期化コールバック

(1) 方法1

通过org.springframework.beans.factory.InitializingBean接口提供下面的方法:
void afterPropertiesSet() throws Exception;
可以简单地实现上述接口和初始化工作可以在afterPropertiesSet()方法中执行,如下所示:
public class ExampleBean implements InitializingBean {
    
    
   public void afterPropertiesSet() {
    
    
      // do some initialization work
   }
}

(2) 方法2

在基于XML的配置元数据的情况下,可以使用init-method属性来指定带有void无参数方法的名称。
例如:
<bean id="exampleBean" class="examples.ExampleBean" init-method="init"/>
下面是类的定义:
public class ExampleBean {
    
    
   public void init() {
    
    
      // do some initialization work
   }
}

4.3.2 破棄コールバック

(1) 方法1

org.springframework.beans.factory.DisposableBean 接口提供下面的方法:
void destroy() throws Exception;
因此,可以简单地实现上述接口并且结束工作可以在destroy()方法中执行,如下所示:
public class ExampleBean implements DisposableBean {
    
    
   public void destroy() {
    
    
      // do some destruction work
   }
}

(2) 方法2

在基于XML的配置元数据的情况下,可以使用destroy-method属性来指定带有void无参数方法的名称。例如:
<bean id="exampleBean" class="examples.ExampleBean" destroy-method="destroy"/>
下面是类的定义:
public class ExampleBean {
    
    
   public void destroy() {
    
    
      // do some destruction work
   }
}

注: Spring の IoC コンテナを非 Web アプリケーション環境 (
リッチ クライアント デスクトップ環境など) で使用している場合は、JVM にシャットダウン フックを登録する必要があります。
そうすることで、すべてのリソースが解放されるように個々の Bean で destroy メソッドを呼び出すことにより、正常なシャットダウンが保証されます

4.3.3 コード例

(1) ファイルHelloWorld.java

package net.biancheng;

public class HelloWorld {
    
    
    private String message;

    public void setMessage(String message) {
    
    
        this.message = message;
    }

    public void getMessage() {
    
    
        System.out.println("message : " + message);
    }

    public void init(){
    
    
        System.out.println("Bean is going through init.");
    }
    public void destroy(){
    
    
        System.out.println("Bean will destroy now.");
    }
}

(2) ファイル MainApp.java
注: ここでは、AbstractApplicationContext クラスで宣言されたフックを閉じるために registerShutdownHook() メソッドを登録する必要があります。これにより、正常なシャットダウンが保証され、関連する destroy メソッドが呼び出されます。

package net.biancheng;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class MainApp {
    
    
    public static void main(String[] args) {
    
    
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        HelloWorld obj = (HelloWorld) context.getBean("helloWorld123");
        obj.getMessage();
        context.registerShutdownHook();
    }
}

(3) ファイルBeans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="helloWorld123" class="net.biancheng.HelloWorld"
          init-method="init" destroy-method="destroy">
        <property name="message" value="Hello World! Testing" />
    </bean>

</beans>

実行後の出力

Bean is going through init.
message : Hello World! Testing
Bean will destroy now.

4.3.4 デフォルトの初期化および破棄方法

同じ名前の初期化メソッドまたは破棄メソッドを持つ Bean が多すぎる場合は、各 Bean で初期化メソッドと破棄メソッドを宣言する必要はありません。
このフレームワークでは、次のように、要素のdefault-init-method属性とdefault-destroy-method属性を使用して、この状況を柔軟に構成できます。

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
    default-init-method="init" 
    default-destroy-method="destroy">

   <bean id="..." class="...">
       <!-- collaborators and configuration for this bean go here -->
   </bean>

</beans>

4.4 ポストプロセッサ

Bean ポストプロセッサを使用すると、初期化メソッドの呼び出しの前後に Bean を追加処理できます。
BeanPostProcessor インターフェースは、独自のインスタンス化ロジック、依存関係解析ロジックなどを提供するために実装できるコールバック メソッドを定義します。Spring コンテナが Bean のインスタンス化、構成、初期化を完了した後、1 つ以上の BeanPostProcessor 実装を挿入することで、いくつかのカスタム ロジック コールバック メソッドを実装することもできます。

複数の BeanPostProcessor インターフェイスを構成でき、これらの BeanPostProcessor インターフェイスの実行順序は、BeanPostProcessor によって実装された Ordered インターフェイスによって提供される order プロパティを設定することによって制御できます。

BeanPostProcessor は Bean (またはオブジェクト) インスタンス上で動作できます。つまり、Spring IoC コンテナが Bean インスタンスをインスタンス化し、BeanPostProcessor インターフェイスがその作業を実行します。

注:
ApplicationContext は、BeanPostProcessor インターフェースの実装によって定義された Bean を自動的に検出し、これらの Bean をポストプロセッサーとして登録し、コンテナー内に Bean を作成することで適切なタイミングでそれを呼び出します。

カスタム BeanPostProcessor インターフェイス実装クラスでは、次の 2 つの抽象メソッド BeanPostProcessor.postProcessBeforeInitialization(Object, String) と BeanPostProcessor.postProcessAfterInitialization(Object, String) を実装する必要があり、正確な名前に注意してください。

そうしないと、「 InitHelloWorld 型は継承された抽象メソッド BeanPostProcessor.postProcessBeforeInitialization(Object, String) を実装する必要があります」のようなエラーが表示されます。
(1) ファイルHelloWorld.java

package net.biancheng;

public class HelloWorld {
    
    
    private String message;

    public void setMessage(String message) {
    
    
        this.message = message;
    }

    public void getMessage() {
    
    
        System.out.println("message : " + message);
    }

    public void init(){
    
    
        System.out.println("Bean is going through init.");
    }
    public void destroy(){
    
    
        System.out.println("Bean will destroy now.");
    }
}

(2) ファイル InitHelloWorld.javaこれは、Bean の初期化の前後に Bean の名前を入力する
BeanPostProcessor を実装する非常に単純な例です組み込み Bean オブジェクトのポストハンドラーにアクセスする方法が 2 つあるため、Bean の初期化の前後でより複雑なロジックを実装できます。

package net.biancheng;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.BeansException;
public class InitHelloWorld implements BeanPostProcessor {
    
    
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    
    
        System.out.println("BeforeInitialization : " + beanName);
        return bean;  // you can return any other object as well
    }
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    
    
        System.out.println("AfterInitialization : " + beanName);
        return bean;  // you can return any other object as well
    }
}

(3) ファイル MainApp.java
注: ここでは、AbstractApplicationContext クラスで宣言されたフックを閉じるために registerShutdownHook() メソッドを登録する必要があります。これにより、正常なシャットダウンが保証され、関連する destroy メソッドが呼び出されます。

package net.biancheng;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
public class MainApp {
    
    
    public static void main(String[] args) {
    
    
        AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        HelloWorld obj = (HelloWorld) context.getBean("helloWorld123");
        obj.getMessage();
        context.registerShutdownHook();
    }
}

(4) ファイルBeans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="helloWorld123" class="net.biancheng.HelloWorld"
          init-method="init" destroy-method="destroy">
        <property name="message" value="Hello World! Testing" />
    </bean>
    <bean class="net.biancheng.InitHelloWorld" />
</beans>

実行後の出力

BeforeInitialization : helloWorld123
Bean is going through init.
AfterInitialization : helloWorld123
message : Hello World! Testing
Bean will destroy now.

4.5 継承の定義

Bean 定義には、コンストラクター パラメーター、プロパティ値、初期化メソッド、静的ファクトリー メソッド名などのコンテナー固有の情報を含む、多くの構成情報を含めることができます。

子 Bean 定義は、親によって定義された構成データを継承します。サブ定義は、必要に応じて一部の値をオーバーライドしたり、他の値を追加したりできます。

Spring Bean 定義の継承は Java クラスの継承とは関係ありませんが、継承の概念は同じです。親 Bean 定義をテンプレートとして定義すると、他の子 Bean が親 Bean から必要な設定を継承できます。

XML ベースの構成メタデータを使用する場合は、親プロパティを使用して子 Bean の定義を示し、親 Bean をプロパティの値として指定します。

おすすめ

転載: blog.csdn.net/qq_20466211/article/details/129653982