通過前兩篇文章的學習,對spring有了初步的認識,並且應該認識到,spring的核心在於控制反轉IOC和依賴注入DI
spring是怎麼達到這個目標呢?
我們都已經知道理利用spring框架,依賴的注入由spring容器來進行,那麼當然需要一些配置信息來告訴spring怎麼注入。這就是spring元數據的配置(即bean的配置)。
綜上,spring通過容器和元數據的配置來實現基本的功能。
通過本文達到,兩個目標:
1.初步的認識spring容器。
2.初步認識spring元數據的配置
ApplicationContext
接口 org.springframework.context.ApplicationContext 代表了Spring IoC容器,它負責實例化、配置、組裝beans. Spring通過讀取元數據的配置進行以上的操作,元數據的配置有多種形式,包括xml、註解和JSR標準。
且Spring 提供了幾種ApplicationContext的實現,如ClassPathXmlApplicationContext、FileSystemXmlApplicationContext,顧名思義,它們讀取基於xml的元數據配置。
程序示例
說明
下面通過一個簡單的例子說明spring容器的簡單用法和spring XMl元數據配置。
這個例子很簡單,就是獲取系統中的用戶,然後打印出來。整個程序分爲三各層次,模擬dao、service和客戶端,客戶端調用service,service調用dao。Service對dao的依賴由spring容器來管理。代碼結構如下圖:
代碼
代碼由客戶端調用開始,一點點深入底層,其中的註釋詳細的說明了相關的要點。
首先是User類:
public class User {
public int id;
public String name;
/**
* @param id
* @param name
*/
public User(int id, String name) {
super();
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
客戶端
客戶端由main函數調用模擬,代碼如下:
package com.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.test.service.UserService;
/**
* @Description: 客戶端首先初始化spring容器,然後從容器中獲取benn調用其相應方法。和傳統不一樣的地方在於,
* 業務對象UserService 的實例化不是由客戶端通過new 來產生,而是直接從spring容器中獲取。
*
* 本示例例環境爲eclipse
*/
public class TestMain {
public static void main(String[] args) {
/**
* ApplicationContext代表spring容器,而ClassPathXmlApplicationContext是它的一個實現,它從類路徑下讀取相應的
* xml 元數據配置,並初始化容器。其中allbean.xml是相應的元數據配置
*/
ApplicationContext context = new ClassPathXmlApplicationContext("allbean.xml");
//從容器中獲取名稱爲 user 的 userService 對象,這個名稱在配置文件之後配置。
UserService userService = context.getBean("user", UserService.class);
System.out.println(userService.getUser());
//可以和傳統方式相比較:
// UserService user = new UserServiceIml();
// UserDao dao = new UserDaoImp();
// ((UserServiceIml)user).setUserDao(dao);
//
// System.out.println(user.getUser());
}
}
allbean.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">
<!--
此配置文件是spring 元數據的配置文件,根標籤爲 beans標籤。
在這個標籤下可以定義由Spring 管理的 bean,其定義形式如下被註釋的地方所示:
基本的配置包括一個容器全局唯一的字符串id,和一個完全限定的類名。
但在這個例子中,有兩個import標籤,分別引入了另外兩個 xml元數據配置文件。
這麼做的好處是,不同的 bean定義對應相應的程序體系架構。
import標籤導入的配置文件路徑是相對路徑,相對於當前文件。
路徑前面可以與斜槓,但不建議這麼做。如下示例不推薦使用
<import resource="/com/test/dao/dao.xml"/>
類似../的路徑也不推薦使用
-->
<import resource="com/test/dao/dao.xml"/>
<import resource="com/test/service/service.xml"/>
<!--
<bean id="bean1" class="..."/>
<bean id="bean2" class="..."/>
-->
</beans>
Service
Service層包含一個接口,一個實現類,一個Spring的xml元數據配置文件:
如下
/**
* 接口
*/
public interface UserService {
public List<User> getUser();
}
/**
*實現類,有個字段引用了UserDao接口,其具體的業務邏輯調用 {@link UserDao#getUser()}實現
*
*且有一個set方法,此set方法由spring 容器注入使用,如果沒有回報錯,
*這是spring容器依賴注入的一種方法--setter注入
*/
public class UserServiceIml implements UserService{
private UserDao userDao;
@Override
public List<User> getUser() {
return userDao.getUser();
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
Xml元數據配置如下,它定義了userServicebean,且定義了它的依賴:
<?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">
<!--
定義了一個由Spring管理的 id爲 user 類型爲com.test.service.UserServiceIml 的 bean,
property 標籤用來定義setter 依賴。
name 屬性 定義依賴的名稱爲 “userDao”(以便通過反射得到seeter方法),此名稱和 UserServiceIml 的字段userDao對應。
ref屬性定義此依賴引用了一個名稱爲 “userDao”的bean (這個bean在dao層定義)
-->
<bean id="user" class="com.test.service.UserServiceIml" >
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
Dao
Dao層定義了相應的 接口,實現類和 xml元數據配置,首先是接口和實現類:
public interface UserDao {
public List<User> getUser();
}
public class UserDaoImp implements UserDao{
@Override
public List<User> getUser() {
List<User> res = new ArrayList<User>();
User a = new User(1, "aa");
User b = new User(2, "bb");
res.add(a);
res.add(b);
return res;
}
}
然後是xml配置文件,定義了一個名稱爲userDao,實現類爲com.test.dao.UserDaoImp 的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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDao" class="com.test.dao.UserDaoImp">
</bean>
</beans>
輸出
運行客戶端程序,輸入如下,和預期一樣:
總結
此文章簡單的說明了Spring容器的用法和相關bean的配置。從一個極簡單例子入手,自頂向下的進行剖析,並簡單的分析了Spring的優點。當然本人目前水平有限,不當之處,歡迎指正。
另外,關於Spring bean的配置還有很多地方需要深入理解,不僅僅是Xml,還有註解、JSR以及他們的組合。bean的配置也包含其他方面,如基本數據類型、集合類型、生命週期、範圍、容器擴展點等,而這些都屬於spring的核心功能,需要逐步理解掌握,期待大家共同進步。