(Spring)Spring框架的核心功能之AOP技術
AOP的概述
1、什麼是AOP的技術???
* AOP為Aspect Oriented Programming的縮寫,意為:面向切面程式設計
* AOP是一種程式設計正規化,隸屬於軟工範疇,指導開發者如何組織程式結構
* AOP最早由AOP聯盟的組織提出的,制定了一套規範。Spring將AOP思想引入到框架中,必須遵守AOP聯盟的規範
* 通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術
* AOP是OOP的延續,是軟體開發中的一個熱點,也是Spring框架中的一個重要內容,是函數語言程式設計的一種衍生範型
* 利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各個部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率
2、AOP:面向切面程式設計(解決了OOP遇到的一些問題)
3、AOP採取橫向抽取機制,取代了傳統縱向繼承體系重複性程式碼(效能監視、事務管理、安全檢查、快取)
4、學習AOP的意義???
* 可以在不修改原始碼的前提下,對程式進行增強!!!
Spring框架的AOP的底層實現
1、Spring框架的AOP技術底層也是採用代理技術,代理的方式提供了兩種
* 基於JDK的動態代理
> 必須是面向介面的,只有實現了具體介面的類才能生成代理物件
* 基於CGLIB動態代理
> 對於沒有實現介面的類,也可以產生代理,產生這個類的子類的方式
2、Spring的傳統AOP中根據類是否實現介面,來採用不同的代理方式
* 如果實現類介面,使用JDK動態代理完成AOP
* 如果沒有實現介面,採用CGLIB動態代理完成AOP
JDK的動態代理
使用Proxy類來生成代理物件
UserDaoImpl:
MyProxyUtils:public class UserDaoImpl implements UserDao { public void save() { System.out.println("儲存客戶..."); } public void update() { System.out.println("修改客戶..."); } }
/**
* 使用JDK的方式生成代理物件
* @author Administrator
*/
public class MyProxyUtils {
public static UserDao getProxy(final UserDao dao) {
ClassLoader loader;
// 使用Proxy類生成代理物件
UserDao proxy = (UserDao) Proxy.newProxyInstance(dao.getClass().getClassLoader(),
dao.getClass().getInterfaces(), new InvocationHandler() {
// 代理物件方法一執行,invoke方法就會執行一次
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("save".equals(method.getName())) {
System.out.println("新增日誌...");
}
// 讓dao類的save或者update方法正常的執行
return method.invoke(dao, args);
}
});
// 返回代理物件
return proxy;
}
}
測試程式碼:
public class Demo1 {
@Test
public void run1() {
// 目標物件
UserDao dao = new UserDaoImpl();
dao.save();
dao.update();
System.out.println("==================================");
// 使用工具類,獲取到代理物件
UserDao proxy = MyProxyUtils.getProxy(dao);
// 呼叫代理物件的方法
proxy.save();
proxy.update();
}
}
CGLIB的代理技術
1)引入CGLIB的開發包* 如果想使用CGLIB的技術來生成代理物件,需要引入CGLIB的開發jar包,在Spring框架核心包中已經引入了CGLIB的開發包。所以直接引入Spring核心開發包即可。。。
2)編寫相關程式碼
BookDaoImpl:
public class BookDaoImpl {
public void save() {
System.out.println("儲存圖書");
}
public void update() {
System.out.println("修改圖書");
}
}
MyCglibUtils:public class MyCglibUtils {
/**
* 使用CGLIB方式生成代理的物件
* @return
*/
public static BookDaoImpl getProxy() {
Enhancer enhancer = new Enhancer();
// 設定父類
enhancer.setSuperclass(BookDaoImpl.class);
// 設定回撥函式
enhancer.setCallback(new MethodInterceptor() {
// 代理物件的方法執行,回撥函式就會執行
public Object intercept(Object obj,Method method,Object[] args,MethodProxy methodProxy) throws Throwable{
if(method.getName().equals("save")) {
System.out.println("記錄日誌...");
}
// 正常執行
return methodProxy.invokeSuper(obj, args);
}
});
// 生成代理物件
BookDaoImpl proxy = (BookDaoImpl) enhancer.create();
return proxy;
}
}
測試程式碼:public class Demo2 {
@Test
public void run1() {
// 目標物件
BookDaoImpl dao = new BookDaoImpl();
dao.save();
dao.update();
System.out.println("==================================");
// 使用CGLIB方式生成代理物件
BookDaoImpl proxy = MyCglibUtils.getProxy();
proxy.save();
proxy.update();
}
}