そして...前のレッスンでは、IoC と DI の理論的な部分を簡単に復習しました。プロジェクト用に pom.xml 構成ファイルもセットアップしました。今日からプログラムの主要部分を作成していきます。まずは、IoC/DIを使用しないプログラムの作成方法を紹介します。そして、依存関係を独自に導入するプログラムを直接作成します。つまり、コードの制御はフレームワークの手に渡されます (気味が悪いように聞こえます)。 私たちがプログラムを運営しているときに、 ある会社があると想像してください。そして、同社には (今のところ) Java 開発部門と採用部門の 2 つの部門があります。「Java 開発部門」を記述するクラスに 2 つのメソッドを持たせます。String getName() - 従業員の名前を返し、String getJob() - 従業員の役職を返します。(リスト 1)
package org.example;
public class JavaDevelopment {
public String getName(){
return "Alexa";
}
public String getJob(){
return "Middle Java developer";
}
}
採用部門を記述するクラスに、従業員を受け入れる入力コンストラクターと、従業員に関する情報を表示する void displayInfo() メソッドを持たせます。(リスト 2)
package org.example;
public class HiringDepartment {
private JavaDevelopment javaDevelopment;
public HiringDepartment(JavaDevelopment javaDevelopment) {
this.javaDevelopment = javaDevelopment;
}
public void displayInfo() {
System.out.println("Name: " + javaDevelopment.getName());
System.out.println("Job: " + javaDevelopment.getJob());
}
}
すべての部門を管理するクラスである Main もあります。(リスト 3)
package org.example;
public class Main {
public static void main(String ... args){
JavaDevelopment javaDevelopment = new JavaDevelopment();
HiringDepartment hiringDepartment = new HiringDepartment(javaDevelopment);
hiringDepartment.displayInfo();
}
}
とりあえず安定。Main クラスを実行すると、次の結果が得られます。
Name: Alexa
Job: Middle Java developer
さて、会社が順調に業績を上げていると想像してみましょう。そこで活動範囲を拡大することを決意し、Python開発部門を開設した。ここで疑問が生じます:この部門をプログラムレベルでどのように説明すればよいでしょうか? 答え: この部門について説明する必要がある場合は、どこにでも「コピーして貼り付ける」必要があります (古き良き方法 🙃)。まず、「Pythonists」部門を記述するクラス自体を作成しましょう。(リスト 4)
package org.example;
public class PythonDevelopment {
public String getName(){
return "Mike";
}
public String getJob(){
return "Middle Python developer";
}
}
そして、それを採用部門に転送します。HiringDepartment はこの部門については何も述べていません。したがって、PythonDevelopment クラスの新しいオブジェクトと、Python 開発者を受け入れるコンストラクターを作成する必要があります。情報が正しく表示されるように、displayInfo() メソッドを変更する必要もあります。(リスト 5)
package org.example;
public class HiringDepartment {
private JavaDevelopment javaDevelopment;
public HiringDepartment(JavaDevelopment javaDevelopment) {
this.javaDevelopment = javaDevelopment;
}
//Тут создается отдел найма для Python - разработчиков
private PythonDevelopment pythonDevelopment;
public HiringDepartment(PythonDevelopment pythonDevelopment) {
this.pythonDevelopment = pythonDevelopment;
}
//Тогда придется изменить метод displayInfo()
public void displayInfo() {
if(javaDevelopment != null) {
System.out.println("Name: " + javaDevelopment.getName());
System.out.println("Job: " + javaDevelopment.getJob());
} else if (pythonDevelopment != null){
System.out.println("Name: " + pythonDevelopment.getName());
System.out.println("Job: " + pythonDevelopment.getJob());
}
}
}
ご覧のとおり、コードの量は 2 倍、あるいはそれ以上になっています。コードの量が多くなると、可読性が低下します。そして最悪なのは、すべてのオブジェクトを手動で作成し、相互に大きく依存するクラスを作成することです。わかりました、これに同意しました。彼らは 1 つの部門について説明しただけです。これで私たちは何も失うことはありません。では、さらに部門を追加したらどうなるでしょうか? 2つある場合はどうなりますか? 三つ?しかし、「採掘と放牧」を禁じた人は誰もいませんでした。 はい、誰も「鉱山と牧草地」を禁止しませんでしたが、それは専門的ではありません。Tyzh はプログラマーです。ここでDIを使用できます。つまり、クラス レベルではなく、インターフェイス レベルで作業します。これで、オブジェクトの状態がインターフェイスに保存されるようになります。こうすることで、クラス間の依存関係が最小限になります。これを行うには、まず開発インターフェイスを作成します。このインターフェイスには、従業員を記述するための 2 つのメソッドがあります。(リスト 6)
package org.example;
public interface Development {
String getName();
String getJob();
}
次に、JavaDevelopment と PythonDevelopment の 2 つのクラスがこのインターフェイスから実装 (継承) し、メソッド String getName() と String getJob() をオーバーライドします。(リスト 7、8)
package org.example;
public class JavaDevelopment implements Development {
@Override
public String getName(){
return "Alexa";
}
@Override
public String getJob(){
return "Middle Java developer";
}
}
package org.example;
public class PythonDevelopment implements Development {
@Override
public String getName(){
return "Mike";
}
@Override
public String getJob(){
return "Middle Python developer";
}
}
次に、HiringDepartment クラスで、Development 型のインターフェイス オブジェクトを定義するだけでよく、そのようなオブジェクトをコンストラクターに渡すこともできます。(リスト 9)
package org.example;
public class HiringDepartment {
private Development development; //Определяем интерфейс
//Конструктор принимает an object интерфейса
public HiringDepartment(Development development){
this.development = development;
}
public void displayInfo(){
System.out.println("Name: " + development.getName());
System.out.println("Job: " + development.getJob());
}
}
見てわかるように、コードの量が減少しています。そして最も重要なことは、依存関係が最小限に抑えられたことです。これらのオブジェクトの値と依存関係は実際にどのように実装されるのでしょうか? 依存関係の注入を行うには 3 つの方法があります。
- コンストラクターの使用
- セッターの使用
- オートワイヤリング(自動バインド)
- XML ファイルの使用 (古い方法)
- 注釈 + XML ファイルの使用 (最新の方法)
- Java コードの使用 (最新の方法)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="javaDeveloper" class="org.example.JavaDevelopment"/>
<bean id="pythonDeveloper" class="org.example.PythonDevelopment"/>
<bean id="hiringDepartment" class="org.example.HiringDepartment">
<constructor-arg ref="javaDeveloper"/>
</bean>
</beans>
さて、順番に。コードの最初の 8 行は私たちにとって興味深いものではなく、デフォルトです。単純にコピーすることができます。<bean> </bean> タグは Spring Bean を定義します。 Bean は、 Spring コンテナによって作成および管理されるオブジェクトです。簡単に言うと、Spring コンテナ自体が新しいクラス オブジェクトを作成します (例: JavaDevelopment javaDevelopment = new JavaDevelopment();)。このタグ内には id 属性と class 属性があります。id はBean の名前を指定します。この ID はオブジェクトにアクセスするために使用されます。これは、Java クラスのオブジェクトの名前に相当します。class - Bean (オブジェクト) がバインドされるクラスの名前を定義します。クラスへのフルパスを指定する必要があります。雇用部門 Bean に注目してください。この Bean 内には、別の <constructor-arg ref="javaDeveloper"/> タグがあります。ここで依存関係の注入が行われます (この例では、コンストラクターを使用した注入)。<constructor-arg> - Spring コンテナが Bean 属性で定義されたクラス コンストラクター内の依存関係を探す必要があることを Spring に指示します。どのオブジェクトを関連付ける必要があるかは、 <constructor-arg> タグ内のref属性によって決まります。ref - 接続する Bean の ID を示します。javaDeveloper の代わりに ref で id pythonDeveloper を指定すると、PythonDevelopmen クラスとの接続が発生します。次に、Main クラスを説明する必要があります。これは次のようになります: (リスト 11)
package org.example;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String ... args){
//Определяем контекст файл в котором содержатся прописанные нами бины
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//Получем бины, которые были определены в файле applicationContext.xml
HiringDepartment hiringDepartment = context.getBean("hiringDepartment", HiringDepartment.class);
hiringDepartment.displayInfo();
context.close(); //Контекст всегда должен закрываться
}
}
ここには何があるの?
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
この行は、Main クラスを Bean を記述する .xml ファイルにリンクします。コンストラクターに渡される値は、.xml ファイルの名前と一致する必要があります。(この例では、applicationContext.xml)。
HiringDepartment hiringDepartment = context.getBean("hiringDepartment", HiringDepartment.class);
HiringDepartment クラスの Bean (オブジェクト) を取得することを示します。最初の引数は、xml ファイルに書き込んだ Bean ID を指します。2 番目の引数は、接続したいクラスを指します。このプロセスはリフレクションと呼ばれます。
hiringDepartment.displayInfo();
context.close(); //Контекст всегда должен закрываться
ここでは HiringDepartment クラスのメソッドを簡単に取得します。オブジェクトを取得するために new キーワードを使用していないこと、および JavaDevelopment または PythonDevelopment タイプの依存オブジェクトをどこにも定義していないことに注意してください。これらは applicationContext.xml ファイルに単純に記述されています。最後の行にも注目してください。シャットダウンする前に、必ずコンテキストを閉じる必要があります。そうしないと、リソースが解放されず、メモリ リークやプログラムの誤動作が発生する可能性があります。ご質問やご提案がございましたら、コメントに書き込んでください。必ずお答えします。清聴ありがとうございました。ソース コードはリンクにあります。 My GitHub カート コースの内容 続きへ...
GO TO FULL VERSION