Spring IOCのBeanオブジェクト
(1)Beanとは
突然、ビーンが何度も言及されていることに気づき、ビーンについて話すのを忘れました。大丈夫です、もう遅すぎません。JavaのBeanは、一種の仕様であり、特別な種類のJavaです。それでは、最初にBean仕様を見てみましょう。
- Beanはパブリッククラスを生成する必要があります。
- すべての属性をカプセル化する必要があり、Beanクラスの属性はプライベートです。
- 属性値は、一連のメソッド(getXxxおよびsetXxx)を介してアクセスおよび変更する必要があります。
- Beanクラスには空のコンストラクター(デフォルトのコンストラクター)が必要です。
これらはBeanの基本的な仕様であり、拡張できますが、これらの最も基本的な仕様は満たされている必要があります。満たされていなければ、標準のBeanとは見なされません。標準Beanの例を挙げましょう。上記の4つの要素に注意してください。
public class User {
private String id;
private String name;
public User(){
}
public User(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
はい、Beanはこのような特別なクラスです。後で頻繁に使用されるため、この点に注意する必要があります。
(2)Beanオブジェクトの3つの構築メソッド
スプリングがあるので、オブジェクトの構築を心配する必要はありません。すべてをスプリングに任せてください。ただし、フレームワークがどれほど高度であっても、その最下層は非常に単純なことを行っており、過去に自分で行うことがよくあります。したがって、Springを学ぶためには、それが何であるのか、またなぜなのかを理解する必要があります。Beanオブジェクトを構築する方法を見てみましょう。ところで、彼らの原理が何であるかを理解してください。
1.工法
これが私たちが最もよく使用する構築方法です。前のケースで、構成ファイルに文を書いたのはなぜですか。
<bean id="circle" class="com.demo.Circle"/>
次に、このBeanオブジェクトは春によって構築され、IOCコンテナに入れられますか?実際、これはそれほど高くありません。実際、Springはリフレクションを使用して、このクラスのデフォルトのコンストラクターを呼び出します。とても簡単です。
問題は、オブジェクトに属性がある場合(当面は、属性に基本的なタイプと文字列のみが含まれると仮定し、オブジェクト属性については後で説明します)、それをどのように構築する必要があるかということです。この構成ファイルの書き方は?非常にシンプルで、各Beanオブジェクトにはセッターメソッドがあります(覚えていない場合は、上記のBeanの構造を確認できます)。フレームワークは、セッターメソッドを呼び出すことにより、必要な値をプロパティに渡すことができます。これはプロパティインジェクションです。たとえば、この記事の冒頭で述べたBeanオブジェクトを作成しようとします。
<bean id="user" class="com.beans.User">
<property name="id" value="666"></property>
<property name="name" value="666"></property>
</bean>
この構成の主な目的は何ですか?まず、いつものように、デフォルトのコンストラクターを呼び出してオブジェクトを作成し、次に2つのセッターメソッドを呼び出して2つのプロパティに値を割り当てます。これは、従来のコードの場合です。
User user = new User();
user.setId("666");
user.setName("666");
もちろん、これを自分で行うことはほとんどありません。プロパティに値を割り当てる必要がある場合は、構築メソッドを直接オーバーライドできます。パラメータを渡すことで、オブジェクトの作成中にプロパティに直接値を割り当てることができ、コードの量を減らすことができます。フレームワークがBeanのパラメーター化された構築メソッドを呼び出す方法を見てみましょう。
<bean id="user" class="com.beans.User" >
<constructor-arg name="id" value="666"></constructor-arg>
<constructor-arg name="name" value="666"></constructor-arg>
</bean>
この構成は、パラメーター化された構築メソッドを直接呼び出すのと同じです。ここで、argは引数(パラメーター)の省略形です。つまり、constructor-argは構築メソッドのパラメーターリストを意味し、名前は明らかにパラメーター名で、値は入力するパラメーター値。したがって、以前と同じように、パラメーターリストのすべてのパラメーターを入力する必要があります。
User user = new User("666", "666");
今、あなたは春のフレームワークが何をするのかという考えを持っているはずです。背の高いフレームワークのように見えるのは、それ以上のものではありません。
2.静的なファクトリ構造
この方法は通常、特定のシナリオでのみ使用されるので、見てみましょう。ここでの静的ファクトリーは、前に説明したファクトリーモデルに似ています。最初に、ファクトリーが必要です。
public class UserFactory {
public static User createPerson(){
return new User();
}
public static User createPerson(Integer id,String name){
return new User(id,name);
}
}
設定ファイルの書き方を見てみましょう:
<bean id="user" class="com.beans.factory.UserFactory" factory-method="createPerson">
<constructor-arg name="id" value="666"></constructor-arg>
<constructor-arg name="name" value="666"></constructor-arg>
</bean>
静的ファクトリメソッドを使用してBeanインスタンスを作成するには、IDに加えて<bean />要素に次の属性を指定する必要があります。
- class:静的ファクトリーの完全なクラス名を指定します(指定されたファクトリーのアドレスに相当)
- factory-method:Beanのインスタンスを作成する静的ファクトリーのメソッドを指定します(Beanを作成するファクトリーのワークショップを指定します)
- メソッドパラメータ:静的なファクトリメソッドがパラメータを必要とする場合は、<constructor-arg />要素を使用して渡します。
3.ファクトリ構造の例
インスタンスファクトリと静的ファクトリの唯一の違いは、必要なBeanオブジェクトを構築する前に、ファクトリオブジェクトをインスタンス化する必要があることです。
<!-- 先构造工厂对象,class指定该工厂的实现类,工厂对象负责产生其他Bean实例 -->
<bean id="userFactory" class="com.beans.factory.UserFactory"/>
<!-- 再引用工厂对象来配置其他Bean -->
<bean id="user" factory-bean="userFactory" factory-method="createPerson">
<constructor-arg name="id" value="666"></constructor-arg>
<constructor-arg name="name" value="666"></constructor-arg>
</bean>
インスタンス化ファクトリを呼び出すには、IDに加えて<bean />に次の属性を指定する必要があります。
- factory-bean:この属性は、ファクトリBeanのIDを指定します
- factory-method:この属性は、インスタンスファクトリのファクトリメソッドを指定します。
- メソッドパラメータ:静的なファクトリメソッドがパラメータを必要とする場合は、<constructor-arg />要素を使用して渡します。
通常、インスタンスファクトリやスタティックファクトリはあまり使われていませんが、通常の開発で最もよく使われる工法は冒頭で述べた工法です。ここで重要な質問があります。Beanオブジェクトの属性がオブジェクトである場合はどうでしょうか。これは、次の依存性注入(DI)についてお話します。
(3)依存性注入
春のIOCと言えば、DIについて話さなければなりませんが、これら2つは基本的には相互に補完し合う関係にあるため、IOCとDIの関係について見ていきます。制御の反転-IOC(制御の反転)は、作成されたオブジェクトの制御の移行を意味します。以前は、オブジェクトを作成するイニシアチブとタイミングは自分で制御していましたが、今ではこの力が春に伝達されます。
IOCの最も重要な機能の1つは、システム操作中にオブジェクトを属性として必要な他のオブジェクトとともに動的に提供することです。これは、DI(依存性注入)によって実現されます。依存関係注入の例を挙げましょう。
たとえば、クラスAではJBDCを使用する必要があります。以前は、クラスAでコードを記述して、新しいConnectionオブジェクトを自分で作成する必要がありました(ここでは、データベース接続プールは考慮していません)。Springでは、構成ファイルを使用して、クラスAでConnectionオブジェクトが必要であることをSpringに通知するだけで済みます。このConnectionがいつどのように構築されるかについては、クラスAが知る必要はありません。実行時に、Springは適切なタイミングでConnectionオブジェクトを構築し、それをクラスAに注入して、各オブジェクト間の関係の制御を完了します。クラスAは、正常に実行するためにConnectionプロパティに依存する必要があり、このConnectionオブジェクトはスプリングによってAに注入されるため、依存関係注入の名前が由来します。
よく読んだ後、前述の依存性注入と属性注入は実際には同じ種類のものであり、どちらも動的にオブジェクトの属性に値を割り当てますが、ここでの属性はオブジェクトであり、上記の属性ですシンプルなタイプです。依存性注入は非常にハイエンドに聞こえますが、実際にはオブジェクトのプロパティに値を割り当てるだけです。
(4)Beanのライフサイクル
構成ファイルの作成方法について説明したので、このBeanの状態が常に春にどのようになるかについて興味があるはずです。それでは、Beanの春のライフサイクルを見てみましょう。ただし、前もって説明しておく必要がある点が1つあります。Springは、シングルトンBeanの完全なライフサイクルの管理にのみ役立ちます。マルチプロトタイプBeanの場合、Springは、フォローアップが作成されてユーザーに渡された後のフォローアップを管理しません。ライフサイクル。シングルトンモードとマルチモードについては、後で説明します。
Beanオブジェクトがどのように生成されるかを見てみましょう。この図は、一見すると非常に恐ろしく見えます。実際、その中の多くのものが拡張ポイントであり、Beanのライフサイクルに散在しています。最初にこれらの拡張ポイントを投げる必要はありません。焦点は、Bean自体のライフサイクルにあるはずです。
実際、Beanのライフサイクルには次の4つの段階しかありません。
インスタンス化
プロパティの割り当て母集団の
初期化初期化
破壊破壊
Springのライフサイクルを完全に理解するには、まずこれらの4つの段階を念頭に置く必要があります。インスタンス化と属性の割り当ては、構築メソッドとセッターメソッドの注入に対応しています。初期化と破棄は、ユーザーがカスタマイズおよび拡張できる2つの段階です。これら2つの関数に必要なロジックを記述できます。これらの4つのステージの間に散在するさまざまな拡張ポイントについては、後で説明します。
まず、最初の3つを見てみましょう。主なロジックはdoCreateBeanメソッドにあります。3つのメソッドは順番に呼び出されます。これらの3つのメソッドは、3つのライフサイクルステージに対応しています。
//PS:下面的代码已经删去暂时不用了解的部分,只留下核心部分
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (instanceWrapper == null) {
// 实例化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 属性赋值
populateBean(beanName, mbd, instanceWrapper);
// 初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
これら3つと1つの破壊により、Beanの4つの最も重要なライフサイクル段階が構成されます。もちろん、下の図に示すように、これらの4つの基本的なライフサイクルステージに加えて、下の図にはいくつかの拡張ポイントも追加されています。
最初はこれらの拡張ポイントの存在を知るだけでよく、使い方については後で使うときに話します。ここで理解する必要があるのは、最も基本的な4つのライフサイクルです。その他の拡張ポイントは、通常の開発ではほとんど使用されませんが、Javaミドルウェアのソースコードを読むときは、これらの拡張ポイントを理解する必要があります。
2020年5月11日