一、Srping框架的AOP技術底層也是採用的代理技術,代理的方式提供了兩種
一、Srping框架的AOP技術底層也是採用的代理技術,代理的方式提供了兩種
1. 基於JDK的動態代理
必須是面向接口的,只有實現了具體接口的類才能生成代理對象
2. 基於CGLIB動態代理
對於沒有實現了接口的類,也可以產生代理,產生這個類的子類的方式
2. Spring的傳統AOP中根據類是否實現接口,來採用不同的代理方式
1. 如果實現類接口,使用JDK動態代理完成AOP
2. 如果沒有實現接口,採用CGLIB動態代理完成AOP
二、代理模式
Proxy Pattern(即:代理模式),23種常用的面向對象軟件的設計模式之一
代理模式的定義:爲其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。
優點:
(1).職責清晰
真實的角色就是實現實際的業務邏輯,不用關心其他非本職責的事務,通過後期的代理完成一件完成事務,附帶的結果就是編程簡潔清晰。
(2).代理對象可以在客戶端和目標對象之間起到中介的作用,這樣起到了的作用和保護了目標對象的作用。
(3).高擴展性
結構
一個是真正的你要訪問的對象(目標類),另一個是代理對象,真正對象與代理
對象實現同一個接口,先訪問代理類再訪問真正要訪問的對象。
代理模式簡單案例
1、jdk動態代理
Java.lang.reflect.Proxy類可以直接生成一個代理對象
Proxy.newProxyInstance():產生代理類的實例。僅能代理實現至少一個接口的類
ClassLoader:類加載器。固定寫法,和被代理類使用相同的類加載器即可。
Class[] interface:代理類要實現的接口。固定寫法,和被代理類使用相同的接口即可。
InvocationHandler:策略(方案)設計模式的應用。如何代理?
InvocationHandler中的invoke方法:調用代理類的任何方法,此方法都會執行
Object proxy:代理對象本身的引用。一般用不着。
Method method:當前調用的方法。
Object[] args:當前方法用到的參數
目標類接口:
public interface WorkInter {
void workInDay(double money);
void workInNight(double money);
}
目標類:
public class Worker implements WorkInter{
@Override
public void workInDay(double money) {
System.out.println("workInDay");
}
@Override
public void workInNight(double money) {
System.out.println("workInNight");
}
}
代理類:
public class JdkProxy {
@Test
public void run() {
WorkInter proxy = (WorkInter) Proxy.newProxyInstance(Worker.class.getClassLoader(), Worker.class.getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("中介費"+((double)args[0])/2);
Object invoke = method.invoke(Worker.class.newInstance(), args);
System.out.println("下班");
return invoke;
}
});
proxy.workInDay(500);
proxy.workInNight(1000);
}
}
執行結果:
2、CGLIB字節碼增強
核心類:Enhancer
- 沒有接口,只有實現類。
- 採用字節碼增強框架 cglib,在運行時 創建目標類的子類,從而對目標類進行增強。
實現步驟:
- 獲得代理類的核心類Enhancer對象
- 設置父類(目標類),setSuperclass()方法,底層是創建目標類的子類
- 設置回調函數enhancer.setCallback(new MethodInterceptor())
- 創建代理對象 create()方法
目標類:
public class Worker{
public void workInDay(double money) {
System.out.println("workInDay");
}
public void workInNight(double money) {
System.out.println("workInNight");
}
}
代理類:
public class WorkerProxy {
@Test
public void run() {
Enhancer enhancer=new Enhancer();
//2.設置父類(目標類),setSuperclass()方法,底層是創建目標類的子類
enhancer.setSuperclass(Worker.class);
//3.設置回調函數enhancer.setCallback(new MethodInterceptor())
enhancer.setCallback(new MethodInterceptor() {
*//**
* Object object:代理對象
* Method method:目標類的方法
* Object[] args:方法的形參
* MethodProxy methodProxy:方法的代理對象
*
*//*
@Override
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// TODO Auto-generated method stub
//開啓事務
//前置通知
System.out.println("代理收取費用"+ (double)args[0]/2);
//執行目標方法,需要目標類實例
Object invoke = method.invoke(Worker.class.newInstance(), (double)args[0]/2);
//後置通知
System.out.println("go home~~~~~");
return invoke;
}
});
//4.創建代理對象 create()方法
Worker workerPeoxy = (Worker) enhancer.create();
workerPeoxy.workInDay(500);
workerPeoxy.workInNight(1000);
}
}