首先講解一下Spring框架,以及爲什麼要使用Spring 框架?
Spring 是一個很好的容器框架, 是輕量級的IoC和AOP的容器框架,主要是針對javaBean的生命週期進行管理的輕量級容器,一般在傳統的java開發中具有高度的耦合性,一個項目中或者一個邏輯功能的實現時,往往一個對象需要依賴很多的對象來完成自己的操作,這樣就造成了兩個類的依賴關係太強,改一個地方,往往牽扯很多類牽扯大量的代碼。
此時Spring就被開發出來, 它可以管理對象和對象之間的依賴關係,我們不需要自己建立對象,把這部分工作全部轉交給容器完成,具有低耦合,對代碼沒有侵略性,對服務器沒有依賴性特點的框架
一個簡單的例子說明使用和不使用框架的區別:
不使用Spring框架
public classUserService{
private UserDao userdao;
public void insert(User user){
userdao = new UserDao(); // 需要自己new一個UserDao類型的對象
userdao.insert(user);
}
}
使用了框架
public classUserService{
private UserDao userdao;
// 設置 set和get函數,在運行時,Spring會將UserDao對象會自動注入到該類中
public UserDao getUserdao() {
return userdao;
}
public void setUserdao(UserDao userdao) {
this.userdao= userdao;
}
public void insert(User user){
userdao.insert(user); // 不需要自己new對象了
}
}
IOC DI
在Spring之中,始終最爲重要的兩個思想就是 控制反轉IOC, 和依賴注入DI 有人認爲 DI(依賴注入)是實現IoC的一種方法,也有人認爲DI 只是IoC的另一種說法。沒有IoC的程序中我們使用面向對象編程對象的創建與對象間的依賴關係完全硬編碼在程序中,對象的創建由程序自己控制,控制反轉後將對象的創建轉移給第三方,個人認爲所謂控制反轉就是:獲得依賴對象的方式反轉了。
java程序中的每個業務邏輯至少需要兩個或以上的對象來協作完成,通常,每個對象在使用他的合作對象時,自己均要使用像new object() 這樣的語法來完成合作對象的申請工作。你會發現:對象間的耦合度高了。而IOC的思想是:Spring容器來實現這些相互依賴對象的創建、協調工作。對象只需要關係業務邏輯本身就可以了。從這方面來說,對象如何得到他的協作對象的責任被反轉了(IOC、DI)
引用一個網上比較火的例子,
那麼IoC是如何做的呢?有點像通過婚介找女朋友,在我和女朋友之間引入了一個第三者:婚姻介紹所。婚介管理了很多男男女女的資料,我可以向婚介提出一個列表,告訴它我想找個什麼樣的女朋友,比如長得像李嘉欣,身材像林熙雷,唱歌像周杰倫,速度像卡洛斯,技術像齊達內之類的,然後婚介就會按照我們的要求,提供一個mm,我們只需要去和她談戀愛、結婚就行了。簡單明瞭,如果婚介給我們的人選不符合要求,我們就會拋出異常。整個過程不再由我自己控制,而是有婚介這樣一個類似容器的機構來控制。Spring所倡導的開發方式就是如此,所有的類都會在spring容器中登記,告訴spring你是個什麼東西,你需要什麼東西,然後spring會在系統運行到適當的時候,把你要的東西主動給你,同時也把你交給其他需要你的東西。所有的類的創建、銷燬都由 spring來控制,也就是說控制對象生存週期的不再是引用它的對象,而是spring。對於某個具體的對象而言,以前是它控制其他對象,現在是所有對象都被spring控制,所以這叫控制反轉。
IoC的一個重點是在系統運行中,動態的向某個對象提供它所需要的其他對象。這一點是通過DI(Dependency Injection,依賴注入)來實現的。比如對象A需要操作數據庫,以前我們總是要在A中自己編寫代碼來獲得一個Connection對象,有了 spring我們就只需要告訴spring,A中需要一個Connection,至於這個Connection怎麼構造,何時構造,A不需要知道。在系統運行時,spring會在適當的時候製造一個Connection,然後像打針一樣,注射到A當中,這樣就完成了對各個對象之間關係的控制。A需要依賴 Connection才能正常運行,而這個Connection是由spring注入到A中的,依賴注入的名字就這麼來的。
那麼DI是如何實現的呢? 反射實現(reflection),它允許程序在運行的時候動態的生成對象、執行對象的方法、改變對象的屬性,spring就是通過反射來實現注入的。
在上面的例子中,使用框架之後在classUserService類中不需要new一個UserDao對象了,取而代之的是 生成set和get方法,這樣在程序運行的時候Spring就可以自己從容器中生成一個UserDao對象,利用反射的方式注入到 該類中。
Spring IOC 實現的一個小例子, 該例子轉載自博客:
http://blog.csdn.net/frightingforambition/article/details/47974775
spring IOC容器的關鍵點:
* 必須將被管理的對象定義到spring配置文件中
* 必須定義構造函數或setter方法,讓spring將對象注入過來
Spring IOC具體如何實現?
上文中的婚介所就是ioc管理對象的容器,實際上是一個xml文件,將對象配置在xml裏面,通過spring的工廠類進行解析,以“反射”的方式創建對象。
我們可以通過下面這裏例子理解spring ioc的實現。本例使用spring 3.2
1.配置applicationContext.xml
<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.2.xsd">
<bean id="userDao4MySqlImpl" class="com.bjsxt.spring.dao.UserDao4MySqlImpl"/>
<bean id="userDao4OracleImpl" class="com.bjsxt.spring.dao.UserDao4OracleImpl"/>
<bean id="userManager" class="com.bjsxt.spring.manager.UserManagerImpl">
<!-- 構造方法注入
<constructor-arg ref="userDao4OracleImpl"/>
-->
<!-- setter方法注入 而且指定注入的對象爲userDao4OracleImpl類型對象-->
<property name="userDao" ref="userDao4OracleImpl"/>
</bean>
</beans>
2.注入的類:
package com.bjsxt.spring.dao;
public interface UserDao {
public void save(String username, String password);
}
package com.bjsxt.spring.dao;
public class UserDao4MySqlImpl implements UserDao {
public void save(String username, String password) {
System.out.println("--------UserDao4MySqlImpl.save()-------");
}
}
package com.bjsxt.spring.dao;
public class UserDao4OracleImpl implements UserDao {
public void save(String username, String password) {
System.out.println("--------UserDao4OracleImpl.save()-------");
}
}
3.被注入的類:
package com.bjsxt.spring.manager;
public interface UserManager {
public void save(String username, String password);
}
package com.bjsxt.spring.manager;
import com.bjsxt.spring.dao.UserDao;
public class UserManagerImpl implements UserManager {
/**
* 兩種方式:如果這個類中需要注入對象,先建立對象屬性,
* 在寫構造方法或者set方法。
*
*/
private UserDao userDao;
/* 構造方法實現
public UserManagerImpl(UserDao userDao) {
this.userDao = userDao;
} */
public void save(String username, String password) {
this.userDao.save(username, password);
}
// set方式實現
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
4.測試類:
package com.bjsxt.spring.client;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.bjsxt.spring.manager.UserManager;
public class Client {
public static void main(String[] args) {
/* 傳統的通過new對象建立類之間的關係
* UserManager userManager = new UserManagerImpl(new UserDao4OracleImpl());
UserManager userManager = new UserManagerImpl(new UserDao4MySqlImpl());
userManager.save("張三", "123");*/
/**
* IOC思想 通過工廠類解析xml文件,以“反射”的方式創建對象:
*/
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
UserManager userManager = (UserManager)factory.getBean("userManager");
userManager.save("張三", "123");
/**
* IOC思想 實際的執行過程,這也是爲什麼需要setter方法或構造方法的原因:
*/
// UserManagerImpl userManager = new UserManagerImpl();
// userManager.setUserDao(new UserDao4OracleImpl()); 根據配置文件可知,這裏set的對象是UserDao4OracleImpl對象
// userManager.save("張三", "123");
}
}
面向Bean
Spring 是面向 Bean 的編程(Bean Oriented Programming, BOP),Bean 在 Spring 中才是真正的主角。Bean 在 Spring 中作用就像 Object 對 OOP 的意義一樣,Spring 中沒有 Bean 也就沒有 Spring 存在的意義。Spring 提供了 IoC容器通過配置文件或者註解的方式來管理對象之間的依賴關係。
Spring 設計的核心 org.springframework.beans 包(架構核心是org.springframework.core包),它的設計目標是與 JavaBean 組件一起使用。這個包通常不是由用戶直接使用,而是由服務器將其用作其他多數功能的底層中介。下一個最高級抽象是 BeanFactory 接口,它是工廠設計模式的實現,允許通過名稱創建和檢索對象。BeanFactory 也可以管理對象之間的關係。
BeanFactory 支持兩個對象模型。
1,單例:模型提供了具有特定名稱的對象的共享實例,可以在查詢時對其進行檢索。Singleton 是默認的,也是最常用的對象模型。對於無狀態服務對象很理想。
2,原型:模型確保每次檢索都會創建單獨的對象。在每個用戶都需要自己的對象時,原型模型最適合。
bean 工廠的概念是 Spring 作爲 IoC容器的基礎。IoC則將處理事情的責任從應用程序代碼轉移到框架。
AOP 面向切面編程 Aspect Oriented Programming
Aop,是一種編程技術,它允許程序員對橫切關注點或橫切典型的職責分界線的行爲(例如日誌和事務管理)進行模塊化。Aop的核心構造是方面,它將那些影響多個類的行爲封裝到可重用的模塊中。Aop的功能完全集成到了 Spring 事務管理、日誌和其他各種特性的上下文中。
舉個例子說明一下吧,比如——————銀行會有這樣的兩個流程, 取款和顯示餘額, 然而在這兩個流程中有着同樣的一個操作:用戶驗證,那麼可不可以把用戶驗證封裝成一個模塊取出來呢? 然後在需要的時候注入到這兩個流程中?
這就是AOP的作用了,有了AOP,你寫代碼時不要把這個驗證用戶步驟寫進去,即完全不考慮驗證用戶,你寫完之後,在另我一個地方,寫好驗證用戶的代碼,然後告訴Spring你要把這段代碼加到哪幾個地方,Spring就會幫你加過去,而不要你自己Copy過去,這樣的好處是當流程變的越來越多時,只需要寫一遍用戶驗證程序,可以節省寫代碼的時間,不過最主要的是你寫代碼的時候,事先只需考慮主流程,而不用考慮那些不重要的流程,在事後就使用AOP就可以給所有流程一次性加入驗證代碼,而你只需要寫一次驗證代碼
所以 AOP的本質是在一系列縱向的控制流程中,把那些相同的子流程提取成一個橫向的面,面向這些橫向的面進行操作。
本文參考了:
https://my.oschina.net/yanquan345/blog/203415
http://blog.csdn.net/frightingforambition/article/details/47974775