所以...上一課我們簡單回顧了IoC和DI的理論部分。我們也為我們的專案設定了 pom.xml 設定檔。今天我們開始創建程式的主要部分。首先,我將向您展示如何在沒有 IoC/DI 的情況下建立程式。然後我們就直接創建一個獨立引入依賴的程式。也就是說,程式碼的控制權傳遞到框架手中(聽起來令人毛骨悚然)。 當我們管理程序時, 想像有一家公司。公司(目前)有兩個部門:Java 開發部和招募部。讓描述「Java開發部門」的類別有兩個方法: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());
}
}
}
正如我們所看到的,程式碼量增加了一倍,甚至更多。程式碼量大了,可讀性就會下降。最糟糕的是我們手動創建所有物件並創建彼此高度依賴的類別。好的,我們同意這一點。他們只是描述了一個部門。我們不會因此而失去任何東西。那麼,如果我們再增加一個部門呢?如果有兩個怎麼辦?三?但沒有人禁止「採礦和放牧」。 是的,沒有人禁止“礦山和牧場”,但這並不專業。Tyzh 是一名程式設計師。這裡你可以使用DI。也就是說,我們不會在類別層級工作,而是在介面層級工作。現在我們物件的狀態將儲存在介面中。這樣,類別之間的依賴關係將最小化。為此,我們首先建立 Development 接口,該接口有兩種用於描述員工的方法。(清單 6)
package org.example;
public interface Development {
String getName();
String getJob();
}
然後讓 JavaDevelopment 和 PythonDevelopment 兩個類別實作(繼承)該介面並重寫 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());
}
}
正如我們所看到的,程式碼量減少了。最重要的是,依賴性被最小化。這些物件的值和依賴關係實際上是如何實現的?依賴注入有以下三種方式:
- 使用建構函數
- 使用設定器
- 自動裝配(自動綁定)
- 使用 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>
現在,按順序。前八行程式碼我們不感興趣,它們是預設的。您可以簡單地複製它們。<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 Spring 容器應該在 bean 屬性中定義的類別建構子中尋找依賴項。需要與哪個物件關聯由<constructor-arg> 標記內的ref屬性決定。ref - 指示要聯絡的 bean 的 id。如果在 ref 而不是 javaDeveloper 中我們指定 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。第二個參數指向我們想要聯繫的類別。這個過程稱為反射。
hiringDepartment.displayInfo();
context.close(); //Контекст всегда должен закрываться
這裡我們很容易得到HiringDepartment類別的一個方法。請注意,我們沒有使用 new 關鍵字來取得對象,也沒有在任何地方定義 JavaDevelopment 或 PythonDevelopment 類型的依賴對象。它們在 applicationContext.xml 檔案中進行了簡單的描述。還要注意最後一行。您應該始終在關閉之前關閉上下文。否則,資源將無法被釋放,並且可能會出現記憶體洩漏或程式錯誤運行。如果有疑問或建議,請寫在評論裡,我一定會解答。感謝您的關注。原始碼位於連結 我的GitHub 購物車 課程內容 待續...
GO TO FULL VERSION