1. 程式人生 > >Spring IOC容器之基礎篇

Spring IOC容器之基礎篇

一、首先簡單熟悉一下Spring框架:

                                       

簡要說明:

IOC:相當於一個大的抽象工廠,通過依賴注入的方式,負責建立物件和管理關係(物件之間的依賴)、Hibernate的session、事務等的管理。

AOP:是一種面向切片的程式設計思想,使用類似jdk的動態代理的方式,來處理一些可以獨立的服務,如,事務、filter等

DAO:jdbc做了一層封裝,同時也有基於HIbernate的封裝。

ORM:Hibernate是對JPA規範的一個實現,iBats是基於sql的一個對映器,TopLink是oracle對jdbc做的一個規範等等,Spring

對這些框架做了整合。

WEB:Spring對諸如Struts(基於請求驅動)以及JSF(基於事件驅動)的框架做了整合。

Spring是一個主要管理業務處理物件的框架,其核心是IOC和AOP。

二、IOC(Inverse of Control):

在每個框架的中都有一個容器的概念,所謂的容器就是將常用的服務,封裝起來,然後,使用者只需要遵循一定的規則,就可以達到統一、靈活、安全、方便、快速的目的。

IOC是一個依賴注入DI(Dependence Injection)的方式達到控制反轉目的的框架。

控制反轉:的優勢在於將服務交給容器。

我們對比一下由我們的應用程式負責服務(物件)定位:

public class UserManagerImpl implements UserManager {


public void addUser(String username, String password) {

//由我們的應用程式負責服務(物件)定位
//UserDao userDao = new UserDao4MySqlImpl();
UserDao userDao = new UserDao4OracleImpl();
userDao.addUser(username, password);
}


}

如果需要更換實現,如果使用應用程式的定位,我們還需要手動去修改程式,這是一件很糟糕的事情。

現在有了容器時候,這個定位就交給了容器,在程式中,只是一個變數的生命,沒有實質的固定的例項化,這個例項化的過程放到了配置檔案,框架在啟動的時候,遵循一個規律,在物件使用之前,已經例項化,這樣就達到了一個動態靈活的目的。

我們看一下,使用容器後的業務處理類(Manager)對資料訪問層實現類(DAO)的程式碼:

public class UserManagerImpl implements UserManager {
	
	private UserDao userDao;
	
/*	public UserManagerImpl(UserDao userDao) {
		this.userDao = userDao;
	}*/
	
	public void addUser(String username, String password) {
		userDao.addUser(username, password);
	}
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
	

}

這裡我們已經看不到例項化的物件了。接下來也正是IOC容器配置的使用。

三、使用容器注入物件:

1、框架搭建:

 1. 提供相關jar包:spring.jar(核心)、commons-logging.jar(不可少)、junit.jar(測試)、log4j-1.2.14.jar(記錄日誌)

 2. 提供配置檔案:applicationContext.xml(注入的核心)、log4j.properties(日誌相關)、放到src(Classpath)檔案下

2、注入:DI

所謂的注入就是按照Spring的約束編寫配置檔案,這裡只列出一些常用的配置方法,其他更多參見文章末尾的api文件下載連結。

1.使用建構函式的注入:

配合使用建構函式:

public class UserManagerImpl implements UserManager {

private UserDao userDao;

public UserManagerImpl(UserDao userDao) {
this.userDao = userDao;
}

public void addUser(String username, String password) {
userDao.addUser(username, password);
}




}
applicationContext.xml中使用constructor-arg標籤:
  <bean id="userManager" class="com.bjpowernode.spring.manager.UserManagerImpl">
  	
   <constructor-arg ref="userDao4Mysql"/> 
   	
  </bean>

2.成員變數方式的注入:

這裡不需要提供關聯類的建構函式,但需要提供set屬性函式:

public class UserManagerImpl implements UserManager {
	
	private UserDao userDao;
	
	public void addUser(String username, String password) {
		userDao.addUser(username, password);
	}
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
	
}

applicationContext.xml使用property標籤:

  <bean id="userManager" class="com.bjpowernode.spring.manager.UserManagerImpl">
  
   	<property name="userDao" ref="usrDao4Oracle" />
   	
  </bean>

兩種方式的對比

使用建構函式注入,具有一定的侷限性,如如果呼叫的類比較多,引數就比較多,這樣處理起來不方便,另外,在一定程度上造成了侵入性,不是一種好的的做法,所以,建議使用屬性注入的方式。

3.普通屬性(包括集合)的注入:

使用容器,注入物件實質是將物件賦值放到了配置檔案中,普通屬性的注入和物件的注入的實質是一樣的,達到的是一個在配置檔案中賦值的目的。

要求注入的屬性必須提供set方法,比較簡單,列出程式碼即可明白:

提供待注入的類以及相關屬性:

public class Bean1 {

	private String  strValue;
	
	private int  intValue;
	
	private String[] arrayValue;
	
	private  List list;
	
	private Set set;
	
	private Map map;
	
	
	public String getStrValue() {
		return strValue;
	}

	public void setStrValue(String strValue) {
		this.strValue = strValue;
	}

	public int getIntValue() {
		return intValue;
	}

	public void setIntValue(int intValue) {
		this.intValue = intValue;
	}

	public String[] getArrayValue() {
		return arrayValue;
	}

	public void setArrayValue(String[] arrayValue) {
		this.arrayValue = arrayValue;
	}

	public List getList() {
		return list;
	}

	public void setList(List list) {
		this.list = list;
	}

	public Set getSet() {
		return set;
	}

	public void setSet(Set set) {
		this.set = set;
	}

	public Map getMap() {
		return map;
	}

	public void setMap(Map map) {
		this.map = map;
	}
	
	
}

完整的配置檔案:
<?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:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd" >

	<bean id="bean1" class="com.bjpowernode.spring.Bean1">
		<property name="strValue" value="ceshi"></property>
		<property name="intValue" value="123"></property>
		<property name="arrayValue">
			<list>
				<value>a</value>
				<value>b</value>
			</list>
		</property>

		<property name="list">
			<list>
				<value> A</value>
				<value> B</value>
			</list>
		</property>

		<property name="set">
			<set>
				<value>M</value>
				<value>N</value>
			</set>
		</property>

		<property name="map">
			<map>
				<entry key="k1" value="v1"></entry>
				<entry key="k2" value="v2"></entry>
			</map>
		</property>
		
	</bean>

	
</beans>

四、使用IOC的好處總結:

1、使用容器,控制反轉,不再需要使用應用程式主動查詢、定位、建立物件,這一切都交給容器統一管理。

2、大量減少了Factory和Singleton的數量,程式碼層次更加清晰。

3、IOC是一個輕量級的框架容器,具有pojo的優勢,沒有侵入性,沒有對其他api的依賴,也不需要實現特殊介面。

4、減少了程式碼的耦合,將物件的賦值,放到了配置檔案中,更容易處理變化。

上面就是SpringIOC容器基本的配置,更多詳細配置,參見這裡的api文件。