【Spring筆記三】Spring中Bean(XML方式裝配)
我們可以把 Spring 看作一個大型的工廠,而 Spring 容器中的 Bean 就是該工廠的產品。要想使用這個工廠生產和管理Bean,就需要在配置檔案中告訴它需要哪些 Bean,以及需要使用何種方法將這些 Bean 裝配到一起。
首先,分清楚 JavaBean 和 Spring 中的 Bean 區別在哪裡,二者是兩個概念不同的東西
1.用處不同:傳統 javabean
2.寫法不同:傳統 javabean 作為值物件,要求每個屬性都提供getter和setter方法;但spring中的bean只需為接受設值注入的屬性提供setter方法。
3.生命週期不同:傳統 javabean 作為值物件傳遞,不接受任何容器管理其生命週期;spring 中的 bean 有 spring 管理其生命週期行為。
總結:在 Spring 中,所有可以被 IOC容器 例項化並管理的 Java類 都可以稱為 Bean。
Spring 中 Bean 的裝配方式有兩種:XML 裝配和 註解 裝配,先說 XML 的方式,下節再寫註解裝配的方式
Bean的裝配(XML方式)
在Spring中,例項化Bean有三種方式,分別為 全類名配置(常用),工廠方法配置(靜態工廠方式 和例項工廠方式),配置Bean(基於FactoryBean)
由於第一種方法比較常用,這裡只寫第一種方法
準備一個 POJO
package com.how2java.pojo; public class Product { private int id; private String name; private Category category; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; } }
然後通過 全類名配置 的方式配置 XML
<bean id="c" class="com.how2java.pojo.Category">
<!--這種屬性注入方式會呼叫Category類中setName方法-->
<property name="name" value="category 1" />
</bean>
<bean name="p" class="com.how2java.pojo.Product">
<property name="name" value="product1" />
<property name="category" ref="c" />
</bean>
注: 1)id 屬性 在 IOC 容器中指的是 Bean 的名稱,且在 IOC 容器中必須是唯一的;
2)如果 id 屬性和 name 都沒有指定,Spring 則會自動將 全類名(即class中的值) 作為 Bean 的名稱。
name (指的是Bean的name)和 id 一樣,Spring都可以通過這這兩個屬性對容器中 Bean 進行配置和管理。不同的是,name屬性可以為 Bean 指定多個名稱,每個名稱用逗號或分好隔開,但Bean的 id 在 Spring 中卻是唯一的。
依賴注入(DI)的方式
在上面配置 XML 時,DI 用的是 屬性注入
<!--這種屬性注入方式會呼叫Category類中setName方法-->
<property name="name" value="category 1" />
這裡寫兩種比較 常用 的注入方式:
1.屬性注入(就如上面的程式碼)
2.構造器注入
使用構造器注入屬性值時,可以指定引數的位置和引數的型別,以區分過載的構造器,它依賴於類中的 構造方法。
<bean id="car" class="com.sun.bean.Car">
<constructor-arg value="Audi" index="0"></constructor-arg>
<constructor-arg value="ShangHai" index="1"></constructor-arg>
<constructor-arg value="203" type="int"></constructor-arg>
</bean>
呼叫的構造器如下:
public Car(String brand, String carp, int maxSpeed) {
this.brand = brand;
this.carp = carp;
this.maxSpeed = maxSpeed;
}
關於屬性注入的更多細節請參考:
https://blog.csdn.net/sun8112133/article/details/80192817
從IOC容器中獲取Bean
從 IOC 容器中獲取 Bean,呼叫的是 getBean() 方法,getBean() 方法是在 BeanFactory 介面中定義的,而 ApplicationContext 介面繼承了 BeanFactory 介面,它提供了BeanFactory所有功能,同時還以一種更加面向框架的方式增強了BeanFactory的功能,主要體現在Context包使用分層和有繼承關係的上下文類。
ApplicationContext在初始化上下文時就例項化所有單例的 Bean,也就是在建立 IOC 容器的時候就例項化所有的單例 Bean。
建立ApplicationContext介面例項,通常採用兩種方法
- ClassPathXmlApplicationContext:從類路徑下載入 xml 配置檔案 (常用)
- FileSystemXmlApplicationContext:從檔案系統中載入配置檔案
最常用的兩種獲取 Bean的方式
1.通過id獲取IOC中的Bean
Product p = (Product) context.getBean("p");
2.通過 全類名 獲取IOC容器中的Bean:
Product p = (Product) context.getBean(Product.class);
package com.how2java.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.how2java.pojo.Product;
public class TestSpring {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "applicationContext.xml" });
Product p = (Product) context.getBean("p");
System.out.println(p.getName());
System.out.println(p.getCategory().getName());
}
}