歡迎來到本篇文章,鴿了好久了,今天繼續寫下 Spring 的內容:Spring 中 Bean 的基本概念、基本寫法和 3 種實例化 Bean 的方式等。 ...
前言
歡迎來到本篇文章,鴿了好久了,今天繼續寫下 Spring 的內容:Spring 中 Bean 的基本概念、基本寫法和 3 種實例化 Bean 的方式等。
什麼是 Bean?
我們回顧下,什麼是 Bean?這在上一篇文章 Spring 核心概念之一 IoC 中說過了,簡而言之,一句話:被 Spring IoC 管理的對象,就是 Bean。
一個 Spring IoC 容器中管理著一個或多個 Bean,這些 Bean 是由我們提供給容器的配置元數據創建的(比如以 XML <bean />
形式定義的 Bean)。
「Bean Definition」的屬性
在容器本身中,這些 Bean 定義被表示為 BeanDefinition
對象,它包含(除其他信息外)以下元數據(metadata)。
- 一個全路徑類名:比如
cn.god23bin.demo.controller.DemoController
,這就是 Bean Definition 的實際實現類。 - Bean 的行為配置元素:它說明瞭 Bean 在容器中的行為方式(比如 scope、生命周期回調等等)。
- 對其他 Bean 的引用:這些被引用的 Bean 被稱為協作者或依賴(collaborators or dependencies)。
- 其他配置的設置:比如,資料庫連接池的大小限制或使用的連接數。
這些元數據對應著每個 Bean Definition 的一組屬性。下表描述了這些屬性:
屬性 | 解釋… |
---|---|
Class | 該屬性是必需的,它指定了用於創建 bean 的 bean 類。 |
Name | 該屬性唯一地指定 bean 標識符。 在基於 XML 的配置元數據中,我們可以使用 id 或 name 屬性來指定 bean 標識符。 |
Scope | 該屬性指定從特定 bean 定義創建的對象的範圍,將在 bean 範圍一章中討論。 |
Constructor arguments | 這用於註入依賴關係,將在後續章節中討論。 |
Properties | 這用於註入依賴關係,將在後續章節中討論。 |
Autowiring mode | 這用於註入依賴關係,將在後續章節中討論。 |
Lazy initialization mode | 懶載入模式,讓 bean 告訴 IoC 容器在第一次被請求時創建一個 bean 實例,而不是在啟動時。 |
Initialization method | 在容器設置了 bean 上的所有必要屬性之後調用的回調。 它將在 bean 生命周期章節中討論。 |
Destruction method | 當包含 bean 的容器被銷毀時要使用的回調。 它將在 bean 生命周期章節中討論。 |
Bean 的命名
以 XML 作為配置元數據的方式中,Bean 定義的基本格式是這樣寫的:
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." class="...">
<!-- 該 bean 的協作者和配置寫在此處 -->
</bean>
<bean id="..." class="...">
<!-- 該 bean 的協作者和配置寫在此處 -->
</bean>
<!-- 更多的 bean 定義寫在此處 -->
</beans>
XML 中類似
<bean/>
由尖括弧組成的寫法,一般稱為「標簽」或者「元素」,在後面的說法中,可能有時出現標簽的說法或者元素的說法,實際上都是指同一個東西,後續便不再說明
我們可以看到,bean 標簽有 id
、class
屬性。
這個 id
是每個 Bean 都有的一個標識符(identifier),這些標識符在 Spring IoC 容器中必須是唯一的。
一個 Bean 一般只有一個標識符。如果它需要一個以上的標識符,那麼多餘的標識符可以被視為別名。
在基於 XML 的配置元數據中,我們可以使用 id
屬性、name
屬性或兩者來指定 Bean 的標識符。
命名習慣
習慣上,這裡對於 Bean 定義的命名和對於我們命名 Java 類中的屬性名是一樣的,就是駝峰命名,小寫字母開頭。比如
userService
、userDao
、loginController
等等。還有,如果想起多個別名,那麼用
name
屬性指定別名是什麼,比如name="別名1,別名2,別名3"
,多個別名之間可以用英文逗號、英文分號或者空格分隔。
Bean 的別名
除了使用 Bean 定義中的 name 屬性來對 Bean 起別名,還可以使用 alias
標簽給 Bean 起別名:
<bean id = "userService" name="userServiceName" ... ></bean>
<alias name="userServiceName" alias="userServiceAliasName" />
這樣,名為 userServiceName
的 Bean 也有了另一個名字:userServiceAliasName
。
Spring 實例化 Bean 的 3 種方式
Spring 可以通過 3 種方式來為我們創建 Bean 對象,創建的對象是根據我們定義的配置元數據來進行創建的。
這 3 種方式分別是:
- 通過構造方法實例化
- 通過靜態工廠方法實例化
- 通過實例工廠方法實例化
在上面的 Bean 定義的屬性中,我們也看到了,在 <bean />
中有一個 class
屬性,就是用來指定要實例化的對象的類型的。一般情況下,這個 class
屬性是必須寫的,除非是通過實例工廠方法實例化的 Bean,那麼它的 Bean 定義可以不需要 class
屬性。
1. 通過構造方法實例化
以 XML 為配置元數據為例,在預設的情況下,我們定義的 Bean 都是以構造方法來實例化 Bean 對象的。
這些交給 Spring 管理的 Bean,不需要實現 Spring 的某某介面或者繼承 Spring 的某某類,只需要有一個無參的構造方法,就可以了。
這裡也是 Spring 低侵入的特點,我們的類根本不需要去實現 Spring 特定的介面或繼承特定的類進而實現 IoC 的功能。
<bean id="fans" class="cn.god23bin.demo.domain.entity.Fans">
<property name="name" value="god23bin" />
</bean>
以上面這個例子來說,這樣定義的 Bean 就是通過 cn.god23bin.demo.domain.entity.Fans
的構造方法實例化的:
package cn.god23bin.demo.domain.entity;
public class Fans {
private String name;
public Fans() {
System.out.println("粉絲無參構造方法被調用了!");
}
// 省略 getter 和 setter
}
從 Spring IoC 容器中獲取被管理的 Fans 對象,這個過程,Spring 就會根據配置元數據去使用構造方法實例化 Fans 對象。
測試:
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Fans fans = applicationContext.getBean(Fans.class);
System.out.println("fans name: " + fans.getName());
輸出:
粉絲無參構造方法被調用了!
fans name: god23bin
2. 通過靜態工廠方法實例化
假設我們有一些對象是從靜態工廠中獲取對象的,有一個靜態工廠類,類中定義了一個靜態方法,該方法是創建對象的:
package cn.god23bin.demo.domain.entity.factory;
import cn.god23bin.demo.domain.entity.Fans;
public class FansStaticFactory {
// 返回 Fans 對象的靜態方法
public static Fans createFansInstance() {
System.out.println("粉絲靜態工廠!");
Fans fans = new Fans();
fans.setName("練習兩年半 | 你幹嘛哎喲~~");
return fans;
}
}
接著在配置元數據中定義 Bean,將通過調用工廠的靜態方法來創建 Bean 對象,使用 class
屬性指定包含了靜態工廠方法的類,使用 factory-method
屬性指定創建對象的靜態方法:
<bean id="fans" class="cn.god23bin.demo.domain.entity.factory.FansStaticFactory" factory-method="createFansInstance" />
測試:
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Fans fans = applicationContext.getBean(Fans.class);
System.out.println("fans name: " + fans.getName());
輸出:
粉絲靜態工廠!
粉絲無參構造方法被調用了!
fans name: 練習兩年半 | 你幹嘛哎喲~~
3. 通過實例工廠方法實例化
實例工廠:
package cn.god23bin.demo.domain.entity.factory;
import cn.god23bin.demo.domain.entity.Fans;
public class FansFactory {
public FansFactory() {
}
public Fans createFansInstance() {
System.out.println("粉絲工廠");
Fans fans = new Fans();
fans.setName("練習兩年半 | 你幹嘛哎喲~~ | 記得關註我噢~");
return fans;
}
}
和靜態工廠實例化 Bean 對象類似,我們這裡用實例廠方法進行 Bean 的實例化,從 Spring IoC 容器中調用現有工廠 Bean 的非靜態方法來創建一個新的 Bean。
這裡需要註意 Fans 這個 Bean 的
class
屬性是不需要的。
<!-- 配置實例工廠 Bean,該對象包含了創建 Fans 對象的名為 createFansInstance 的方法 -->
<bean id="fansFactory" class="cn.god23bin.demo.domain.entity.factory.FansFactory">
<!-- 工廠的其他需要的依賴對象就配置在這裡 -->
</bean>
<!-- 這個 Bean 將通過實例工廠創建 -->
<bean id="fans" factory-bean="fansFactory" factory-method="createFansInstance" />
總結
以上,就是本文的所有內容,主要介紹了 Spring 中 Bean 的概念和 Bean 的定義屬性。
Bean 由配置元數據創建,比如以XML形式定義的 Bean。Bean 在容器中由 BeanDefinition 對象表示,它包含類名、行為配置元素、對其他 Bean 的引用以及其他配置設置等元數據屬性。
Bean 的命名方式一般就是駝峰命名的。在基於XML的配置元數據中,可以使用 id 屬性或 name 屬性來指定 Bean 的標識符,Bean 的別名可以使用 alias 標簽進行定義。
最後,我們說了 Spring 實例化 Bean 的三種方式:通過構造方法實例化、通過靜態工廠方法實例化和通過實例工廠方法實例化。
當然,Bean 的內容不止這些,本文是對 Bean 的初步介紹。下一篇我們將介紹 Bean 之間的依賴關係,通過依賴註入來實現 Bean 之間的相互依賴。
最後的最後
希望各位屏幕前的靚仔靚女們
給個三連!你輕輕地點了個贊,那將在我的心裡世界增添一顆明亮而耀眼的星!
咱們下期再見!