前回の記事では、Spring とは何か、Bean とコンテキストとは何かについて簡単に説明しました。さあ、試してみましょう。IntelliJ IDEA Enterprise Editionを使用して実行します。ただし、私の例はすべて、無料の IntelliJ IDEA Community Edition でも動作するはずです。スクリーンショットで、あなたが持っていないウィンドウがあることがわかりましたが、心配しないでください。このプロジェクトにとっては重要ではありません :)
まず、空の Maven プロジェクトを作成します。この方法については、このリンクの記事で説明しました。「 Maven プロジェクトを Web プロジェクトに変換する時期が来ました。 」という文言まで読んでください。その後、この記事では Web プロジェクトの作成方法が示されていますが、現時点ではその必要はありません。src/main/java内フォルダーにパッケージを作成します (私の場合は、「 」と名付けました
左側のウィンドウに、パッケージと

en.codegym.info.fatfaggy.animals
。好きな名前を付けることができます。ただし、すべての適切な場所で、私のパッケージ名を実際のパッケージ名に置き換えることを忘れないでください。次に、クラスを作成しMain
、方法
public static void main(String[] args) {
...
}
その後、pom.xml ファイルを開いてdependencies
セクションを追加します。次に、Maven リポジトリに移動し、最新の安定バージョンのSpring コンテキストを見つけます。見つけたものをdependencies
セクションに記入します。このプロセスについては、 CodeGym の他の記事で詳しく説明しました(「 Maven での依存関係の接続」というタイトルのセクションを参照)。その後、Maven 自体が必要な依存関係を見つけてダウンロードします。最終的には、次のような結果が得られるはずです。 
Main
クラスを含むプロジェクト構造が表示されます。中央のウィンドウは、pom.xml がどのように見えるかを示しています。プロパティも追加しましたセクションを参照してください。このセクションでは、ソース ファイルで使用している Java のバージョンとコンパイルするバージョンを Maven に指示します。これは、古いバージョンの Java を使用していることを IDEA が警告しないようにするためです。これはオプションです:) 右側のウィンドウを見ると、spring-context モジュールを接続しただけであっても、spring-core、spring-beans、spring-aop、spring-expression モジュールが自動的に取り込まれたことがわかります。各モジュールを個別に接続して、各モジュールの依存関係を pom.xml ファイル内の明示的なバージョンで書き出すこともできましたが、今のところは現状のままで問題ありません。次に、パッケージを作成し、entities
その中に 3 つのクラス、、、を作成しCat
ますDog
。Parrot
それぞれの動物に名前を付けてみましょう(private String name
— 一部の値をハードコーディングできます)。ゲッター/セッターはパブリックです。Main
次にクラスとメソッドに進みmain()
、次のように書きます。
public static void main(String[] args) {
// Create an empty Spring context that will look for its own beans based on the annotations in the specified package
ApplicationContext context =
new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.entities");
Cat cat = context.getBean(Cat.class);
Dog dog = (Dog) context.getBean("dog");
Parrot parrot = context.getBean("parrot-polly", Parrot.class);
System.out.println(cat.getName());
System.out.println(dog.getName());
System.out.println(parrot.getName());
}
まず、コンテキスト オブジェクトを作成し、Bean を見つけるためにどのパッケージを調べるかをコンストラクターに指示します。言い換えれば、Spring はこのパッケージを調べて、Bean であることを示す特別なアノテーションが付けられたクラスを見つけようとします。次に、これらのクラスのオブジェクトを作成し、コンテキストに配置します。その後、このコンテキストから猫を取得します。コンテキスト オブジェクトを呼び出して、必要なオブジェクトのクラスを示す Bean (オブジェクト) を提供します (ちなみに、クラスだけでなくインターフェイスを指定することもできます)。その後、Spring は要求されたクラスのオブジェクトを返し、それを変数に保存します。次に、Spring に「dog」という Bean を取得してもらいます。Spring がDog
これはクラス名ですが、最初に小文字が付きます。この場合、クラスは という名前なDog
ので、Bean の名前は「dog」になります。そこにオブジェクトが必要な場合BufferedReader
、Spring はそれに「bufferedReader」という名前を付けます。そして、Java はどのクラスが必要かを 100% 確信することはできないため、オブジェクトを返しObject
、それを手動で目的の型にキャストします。Dog
。クラスを明示的に指定するオプションの方が便利です。3 番目のオプションは、クラス名と Bean 名によって Bean を取得することです。コンテキストには単一クラスの複数の Bean が含まれる可能性があります。必要な特定の Bean を示すために、その名前を示します。ここではクラスも明示的に指定しているため、キャストを実行する必要はなくなりました。 重要!Spring が要件に一致する Bean を複数見つけた場合、どの Bean を提供するかを決定できないため、例外がスローされます。したがって、この状況を回避するには、必要な Bean を Spring にできるだけ具体的に伝えるようにする必要があります。Spring がコンテキストを検索し、要件に一致する Bean を 1 つも見つけられなかった場合も、例外がスローされます。最後に、動物の名前を表示するだけで、本当に必要なオブジェクトが得られたかどうかを確認できます。しかし、今プログラムを実行すると、Spring が不幸であることがわかります。そのコンテキスト内で必要な動物を見つけることができません。これは、これらの Bean が作成されていないためです。前に述べたように、Spring はクラスをスキャンするときに、独自の Spring アノテーションを探します。そして、Spring がこれらのアノテーションを見つけられない場合、それは見つかりません。これらのクラスが、作成する必要がある Bean に対応するとは考えられません。これを修正するには、単に次のコードを追加する必要があります。@Component
各動物クラスの前に注釈を付けます。
@Component
public class Cat {
private String name = "Oscar";
...
}
しかし、それだけではありません。このクラスの Bean に特定の名前を付ける必要があることを Spring に明示的に伝える必要がある場合は、アノテーションの後に括弧内に名前を示します。たとえば、parrot-polly
メソッド内でこのオウムを取得するために使用する名前である " " という名前をオウム Bean に付けるように Spring に指示するにはmain
、次のようなことを行う必要があります。
@Component("parrot-polly")
public class Parrot {
private String name = "Polly";
...
}
これが自動構成 の要点です。クラスを作成し、必要なアノテーションを付けて、そのクラスを含むパッケージを Spring に伝えます。これは、フレームワークが注釈を検索し、これらのクラスのオブジェクトを作成するために実行するパッケージです。ちなみに、Spring は@Component
アノテーションだけでなく、このアノテーションを継承する他のすべてのアノテーションも検索します。たとえば@Controller
、、、、、などです。これについて@RestController
は、今後の記事で紹介します。次に、 Java ベースの構成を使用して同じことを実行してみます。開始するには、@Service
@Repository
@Component
私たちのクラスからの注釈。物事をさらに難しくするために、これらのクラスは私たちが作成したものではないため、簡単に変更できない、つまりアノテーションを追加できないと想像してください。これらのクラスが何らかのライブラリにパッケージ化されているようなものです。この場合、これらのクラスを Spring で認識されるように編集する方法はありません。しかし、これらのクラスのオブジェクトが必要です。ここでは、オブジェクトを作成するために Java ベースの構成が必要です。まず、 のような名前のパッケージを作成しますconfigs
。このパッケージでは、 のような通常の Java クラスを作成し、MyConfig
それに@Configuration
アノテーションを付けます。
@Configuration
public class MyConfig {
}
main()
次に、メソッドを微調整して、コンテキストの作成方法を変更する 必要があります。どのクラスに設定があるかを明示的に示すこともできます。
ApplicationContext context =
new AnnotationConfigApplicationContext(MyConfig.class);
Bean を作成する複数の異なるクラスがあり、それらのいくつかを同時に接続したい場合は、単純にそれらをすべてカンマで区切って指定します。
ApplicationContext context =
new AnnotationConfigApplicationContext(MyConfig.class, MyAnotherConfig.class);
それらの数が多すぎて、すべてを同時に接続したい場合は、単にそれらが含まれているパッケージの名前を指定します。
ApplicationContext context =
new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.configs");
この場合、Spring はパッケージを調べて、アノテーションが付けられたすべてのクラスを見つけます@Configuration
。構成がさまざまなパッケージに分割されている非常に大きなプログラムがある場合は、構成を含むパッケージの名前をカンマ区切りのリストで指定するだけです。
ApplicationContext context =
new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.database.configs",
"en.codegym.info.fatfaggy.animals.root.configs",
"en.codegym.info.fatfaggy.animals.web.configs");
または、すべてに共通するパッケージの名前:
ApplicationContext context =
new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals");
好きなように実行できますが、構成を持つクラスを単に示す最初のオプションが私たちのプログラムに最も適しているように思えます。コンテキストを作成するとき、Spring はアノテーションが付けられたクラスを探し@Configuration
、これらのクラスの独自のオブジェクトを作成します。アノテーションが付けられたメソッドの呼び出しを試みます@Bean
。つまり、これらのメソッドは、Spring がコンテキストに追加する Bean (オブジェクト) を返します。次に、Java ベースの構成を使用して、クラス内に猫、犬、オウムの Bean を作成します。これは非常に簡単に実行できます。
@Bean
public Cat getCat() {
return new Cat();
}
ここでは手動で cat を作成し、Spring に渡します。Spring はオブジェクトをそのコンテキスト内に保持します。Bean に明示的に名前を付けていないため、Spring はメソッドの名前と同じ名前を Bean に付けます。この場合、キャットビーンは「getCat
」と呼ばれます。ただし、メソッド内で Cat Bean を取得するには名前ではなくクラスを使用するためmain
、Bean の名前は重要ではありません。同様に、Spring が Bean にメソッド名を与えることに留意して、Dog Bean を作成します。Parrot Bean に明示的に名前を付けるには、@Bean
アノテーションの後に括弧内にその名前を指定するだけです。
@Bean("parrot-polly")
public Object weNeedMoreParrots() {
return new Parrot();
}
ご覧のとおり、ここではObject
戻り値の型を指定し、メソッドに任意の名前を付けました。ここで名前を明示的に指定したため、これは Bean の名前には影響しません。それでも、多かれ少なかれ意味のある戻り値とメソッド名を示す方が良いでしょう。1 年後にプロジェクトを再開するときに自分自身に利益をもたらすため以外の理由がない場合は、これを実行してください。:) 次に、別の Bean を作成するために 1 つの Bean が必要な状況を考えてみましょう。たとえば、Cat Bean 内の猫の名前を、オウムの名前に文字列「-killer」を加えたものにしたいとします。問題ない!
@Bean
public Cat getCat(Parrot parrot) {
Cat cat = new Cat();
cat.setName(parrot.getName() + "-killer");
return cat;
}
ここで Spring は、この Bean を作成するには、フレームワークが以前に作成した Parrot Bean を渡す必要があることを認識します。したがって、必要なメソッド呼び出しのチェーンが調整されます。まず、parrot 作成メソッドが呼び出され、次にフレームワークが新しい parrot を cat 作成メソッドに渡します。ここで依存性注入が登場します。Spring 自体が必要な Parrot Bean をメソッドに渡します。IDEA が変数について怒った場合はparrot
、オウム作成メソッドの戻り値の型を から に変更することを忘れないでObject
くださいParrot
。さらに、Java ベースの構成により、あらゆる Java コードを実行できます。Bean 作成メソッド内で。他の補助オブジェクトを作成したり、Spring アノテーションが付いていなくても他のメソッドを呼び出したり、ループやブール条件を作成したり、思いついたことなら何でもできます。これは自動構成ではすべて可能というわけではありませんし、XML 構成ではさらに不可能です。 ここで、もう少し楽しい問題を考えてみましょう。ポリモーフィズムとインターフェイス:)インターフェイス を作成しWeekDay
、このインターフェイスを実装する 7 つのクラス、Monday
、Tuesday
、Wednesday
、、、を作成します。インターフェースに、対応するクラスの曜日の名前を返すメソッドを与えます。つまり、クラスは「」を返します。Thursday
Friday
Saturday
Sunday
String getWeekDayName()
Monday
Monday
アプリケーションの起動時に、現在の曜日に対応する Bean をコンテキストに入れることがタスクだとします。インターフェースを実装するすべてのクラスの Bean ではなく、必要な Bean だけを使用できますWeekDay
。それを次のようにしてください:
@Bean
public WeekDay getDay() {
DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
switch (dayOfWeek) {
case MONDAY: return new Monday();
case TUESDAY: return new Tuesday();
case WEDNESDAY: return new Wednesday();
case THURSDAY: return new Thursday();
case FRIDAY: return new Friday();
case SATURDAY: return new Saturday();
default: return new Sunday();
}
}
ここで、戻り値の型はインターフェイスです。このメソッドは、現在の曜日に応じて、インターフェイスを実装するいずれかのクラスの正規のオブジェクトを返します。これで、メソッド内で次のことができるようになりますmain()
。
WeekDay weekDay = context.getBean(WeekDay.class);
System.out.println("Today is " + weekDay.getWeekDayName() + "!");
私にとって、プログラムは今日が日曜日であることを教えてくれます :) 明日プログラムを実行すると、コンテキストにはまったく異なるオブジェクトが含まれると確信しています。単にインターフェースを使用して Bean を取得していることに注意してください: context.getBean(WeekDay.class)
。Spring は、インターフェースを実装する Bean のコンテキストを検索し、それを返します。次に、変数が最終的に Sunday オブジェクトになることがわかりWeekDay
、この変数を操作するときによく知られているポリモーフィズムの概念が適用されます。:) 次に、結合されたアプローチについて少し説明します。このアプローチでは、一部の Bean は Spring によって自動的に作成され、一部の Bean はアノテーションを持つクラスのパッケージをスキャンすることによって作成され@Component
、その他の Bean は Java ベースの構成によって作成されます。これを検討しながら、元のバージョンに戻りますCat
。Dog
Parrot
クラスには@Component
注釈が付けられました。Spring にパッケージを自動的にスキャンさせて動物用の Bean を作成したいとしますentities
が、先ほどと同様に曜日を含む Bean も作成したいとします。必要なのは、クラス@ComponentScan
のレベルでアノテーションを追加することだけですMyConfig
。これは、 でコンテキストを作成するときに指定しmain()
、スキャンして必要なクラスの Bean を自動的に作成する必要があるパッケージを括弧内に指定します。
@Configuration
@ComponentScan("en.codegym.info.fatfaggy.animals.entities")
public class MyConfig {
@Bean
public WeekDay getDay() {
DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
switch (dayOfWeek) {
case MONDAY: return new Monday();
case TUESDAY: return new Tuesday();
case WEDNESDAY: return new Wednesday();
case THURSDAY: return new Thursday();
case FRIDAY: return new Friday();
case SATURDAY: return new Saturday();
default: return new Sunday();
}
}
}
コンテキストを作成するとき、Spring はMyConfig
クラスを処理する必要があることを認識します。クラスに入り、「en.codegym.info.fatfaggy.animals.entities
」パッケージをスキャンしてそれらのクラスの Bean を作成する必要があることを確認した後、MyConfig
クラスのgetDay()
メソッドを実行してWeekDay
Bean をコンテキストに追加します。このmain()
メソッドでは、必要なすべての Bean (動物オブジェクトと曜日を含む Bean の両方) にアクセスできるようになりました。Spring に XML 設定ファイルも取得させる必要がある場合は、独自の Web 検索を行って説明を見つけることができます :) 要約:
- 自動構成を使用してみる
- 自動構成中に、Bean を作成する必要があるクラスを含むパッケージの名前を指定します。
- これらのクラスには
@Component
注釈が付いています。 - Spring はこれらすべてのクラスを実行し、オブジェクトを作成してコンテキストに配置します。
- 何らかの理由で自動構成が適さない場合は、Java ベースの構成を使用します。
- この場合、必要なオブジェクトを返すメソッドを持つ通常の Java クラスを作成します。
@Configuration
コンテキストの作成時に構成で特定のクラスを指定するのではなく、パッケージ全体をスキャンする場合は、このクラスにアノテーションを付けます。 - Bean を返すこのクラスのメソッドには、
@Bean
注釈が付いています。
@ComponentScan
アノテーションを使用します。
GO TO FULL VERSION