Spring 容器介紹

2023-07-19 18:01:43

Spring IoC 容器

Spring IoC 容器是 Spring 框架的核心元件之一。IoC(Inverse of Control,控制反轉)的含義是:

  1. 將物件的建立交給 Spring 容器,而不是由程式自己直接 new 範例。這樣可以實現解耦。
  2. Spring 容器會在程式啟動時,根據物件的設定元資訊(XML或註解),生成相應的物件範例並注入到需要使用的地方。

Spring IoC 容器具體提供以下功能:

  1. 管理 beans 生命週期:載入設定、範例化、裝配屬性、執行初始化方法等。
  2. 通過依賴注入(DI, Dependency Injection),將 beans 的依賴給提供。
  3. 通過依賴查詢,根據 id 或 name 從容器查詢 bean 的範例。
  4. 支援多種設定元資訊,使用 XML 設定、註解設定或 Java API 設定。
  5. 支援自動裝配 beans 之間的依賴關係。
  6. 管理多個不同的 beans 範例。
  7. 包括很多應用裡常見的 beans,如 Hibernate、JDBC 等。

總的說,Spring IoC 容器就是一個 bean 範例倉庫,用來管理程式所有的物件生命週期,以及物件間的依賴。
目的是:

  1. 解耦:物件的建立、設定與依賴獲取通過設定方式實現,不需要在程式碼中 new 範例。
  2. 依賴注入:Spring 容器會自動將 beans 的依賴注入進來,不需要手動 new 和賦值。
  3. 大大增強可測試性。
  4. 整合各種框架方便。

Spring BeanFactory 容器

  1. BeanFactory是SpringIOC容器的基本介面,定義了IOC容器的基礎功能規範。

  2. BeanFactory主要提供了兩大功能:
    (1)Bean範例化 - 通過設定元資訊範例化、設定Bean
    (2)依賴注入 - 將Bean的依賴關係注入到Bean中

  3. Spring中有多種BeanFactory介面實現:
    (1)最常用的是XmlBeanFactory,它從XML組態檔中讀取元資訊,用於範例化、設定Bean
    (2)其他實現還有GroovyBeanFactory、ClassPathXmlApplicationContext等

  4. 使用場景:
    (1)適用於資源有限的應用場景,如行動端、Applet等
    (2)也可用於希望更底層控制IOC容器的場景

  5. BeanFactory的優點:
    (1)精簡,不需要過多功能
    (2)資源佔用少,適合使用者端應用
    (3)可自定義程度高

  6. BeanFactory的缺點:
    (1)需要自行編碼讀取設定、獲取Bean範例
    (2)不支援企業級功能,擴充套件性差
    (3)與Spring高階容器整合困難

  7. 更高階的容器ApplicationContext建立在BeanFactory基礎之上,提供了事務、AOP等企業級功能,是更常用的首選。

  8. BeanFactory相關介面如BeanFactoryAware等主要是為了相容舊版本程式碼和整合第三方框架。

  9. 一般情況下,使用ApplicationContext為主,只有在資源受限或者需要底層控制時,才會考慮使用BeanFactory。

綜上,BeanFactory主要設計為一個輕量級的IOC容器,提供了Spring IOC的基礎功能,但實際應用中,更多地使用的是功能更全面的ApplicationContext。

下面是檔案 HelloWorld.java 的內容:

package com.tutorialspoint;
public class HelloWorld {
   private String message;
   public void setMessage(String message){
    this.message  = message;
   }
   public void getMessage(){
    System.out.println("Your Message : " + message);
   }
}

下面是檔案 MainApp.java 的內容:

package com.tutorialspoint;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class MainApp {
   public static void main(String[] args) {
      XmlBeanFactory factory = new XmlBeanFactory
                             (new ClassPathResource("Beans.xml"));
      HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");
      obj.getMessage();
   }
}

在主程式當中,我們需要注意以下兩點:

  • 第一步利用框架提供的 XmlBeanFactory() API 去生成工廠 bean 以及利用 ClassPathResource() API 去載入在路徑 CLASSPATH 下可用的 bean 組態檔。XmlBeanFactory() API 負責建立並初始化所有的物件,即在組態檔中提到的 bean。
  • 第二步利用第一步生成的 bean 工廠物件的 getBean() 方法得到所需要的 bean。 這個方法通過組態檔中的 bean ID 來返回一個真正的物件,該物件最後可以用於實際的物件。一旦得到這個物件,你就可以利用這個物件來呼叫任何方法。

下面是組態檔 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="helloWorld" class="com.tutorialspoint.HelloWorld">
       <property name="message" value="Hello World!"/>
   </bean>

</beans>

如果你已經完成上面的內容,接下來,讓我們執行這個應用程式。如果程式沒有錯誤,你將從控制檯看到以下資訊:

Your Message : Hello World!

Spring ApplicationContext 容器

Spring ApplicationContext 容器是 Spring IoC 容器的一種具體實現,是 Spring 框架中最重要的容器之一。與 BeanFactory 容器相比,ApplicationContext 容器提供了更多的功能和特性。

ApplicationContext 容器在啟動時會讀取組態檔或者註解,自動建立和管理 Bean 範例,並在需要的時候將它們注入到其他 Bean 中。同時,ApplicationContext 容器還提供了以下功能:

  1. 國際化支援:可以方便地實現多語言支援。

  2. 事件傳播:可以方便地實現事件驅動的程式設計模型。

  3. AOP 支援:可以方便地實現面向切面程式設計。

  4. Web 應用支援:可以方便地實現 Spring MVC、RESTful Web Services 等 Web 應用。

  5. 安全性支援:可以方便地實現基於 Spring Security 的安全控制。

  6. JMS 支援:可以方便地實現基於 JMS 的訊息傳遞。

在使用 ApplicationContext 容器時,可以選擇不同的實現方式,如 XML 設定、註解設定、Java 設定等。無論使用哪種方式,都可以通過 ApplicationContext 容器來管理應用程式中的物件,從而實現了應用程式的靈活性和可延伸性。

需要注意的是,ApplicationContext 容器是一個重量級的容器,因為它在啟動時會自動建立和裝配所有 Bean 範例。如果應用程式中的 Bean 數量較多,或者組態檔較大,啟動時間可能會較長。因此,在一些特定場景下,可以使用 BeanFactory 容器來代替 ApplicationContext 容器,以提高應用程式的啟動速度。

下面是一個使用 Spring ApplicationContext 容器實現的 HelloWorld 範例程式碼:

首先,需要在 pom.xml 檔案中新增 Spring 相關依賴:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.9</version>
    </dependency>
</dependencies>

然後,在 resources 目錄下,建立一個名為 applicationContext.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.xsd">

    <bean id="helloWorld" class="com.example.HelloWorld">
        <property name="message" value="Hello, World!"/>
    </bean>

</beans>

在上面的組態檔中,定義了一個名為 helloWorld 的 Bean,它的型別是 com.example.HelloWorld,並且設定了一個名為 message 的屬性,值為 "Hello, World!"。

接下來,編寫 HelloWorld 類:

package com.example;

public class HelloWorld {
    private String message;

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

    public void printMessage() {
        System.out.println(message);
    }
}

在上面的程式碼中,定義了一個名為 message 的屬性和一個名為 printMessage() 的方法,用於列印訊息。

最後,在主方法中,使用 ApplicationContext 容器來獲取 HelloWorld 範例,並呼叫其 printMessage() 方法:

package com.example;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
        obj.printMessage();
    }
}

在上面的程式碼中,使用 ClassPathXmlApplicationContext 類建立一個 ApplicationContext 容器,並指定組態檔的路徑為 applicationContext.xml。然後,通過 getBean() 方法獲取名為 helloWorld 的 Bean 範例,並將其強制轉換為 HelloWorld 型別。最後,呼叫 printMessage() 方法列印訊息 "Hello, World!"。

執行上述程式碼,輸出的結果為:Hello, World!