- 為對象提供一個替身,以控制對這個對象的訪問锨阿。即通過代理對象訪問目標(biāo)對象,這樣做的好處是:可以在目標(biāo)對象實(shí)現(xiàn)的基礎(chǔ)上,增加額外的功能操作记罚,即擴(kuò)展目標(biāo)對象的功能
- 主要有三種不同形式:靜態(tài)代理墅诡、JDK動態(tài)代理(接口代理)和cglib代理;
- 靜態(tài)代理(如AspectJ)
- JDK動態(tài)代理(接口代理)
- Cglib代理(可以在內(nèi)存動態(tài)的創(chuàng)建對象,而不需要實(shí)現(xiàn)接口,屬于動態(tài)代理范疇)
靜態(tài)代理
缺點(diǎn):代理對象和目標(biāo)對象都需要實(shí)現(xiàn)一樣的接口,一旦接口增加方法,目標(biāo)對象和代理對象都要維護(hù)。
JDK動態(tài)代理(接口代理)
- 代理類所在的包:java.lang.reflect.Proxy
- 核心:使用 newProjectInstance(,,) 方法
// 返回代理對象
Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)
// 調(diào)用代理對象方法時:執(zhí)行被代理對象的方法
method.invoke(obj,args);
使用示例:
public class ProxyFactory {
// 傳進(jìn)來要被代理的對象
private Object obj;
public ProxyFactory(Object obj){
this.obj=obj;
}
// 通過被代理對象桐智,獲取代理對象
public Object getProxyObj(){
// 第二個參數(shù)是接口數(shù)組
Object proxyObj=Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理開始");
// 接口方法,args是當(dāng)前調(diào)用方法的參數(shù)
Object returnVal=method.invoke(obj,args);
System.out.println("代理提交");
// 動態(tài)調(diào)用方法的返回值
return returnVal;
}
});
return proxyObj;
}
}
Cglib代理(有時候?qū)ο蟛]有實(shí)現(xiàn)接口,使用目標(biāo)對象子類來實(shí)現(xiàn)代理,攔截器)
Cglib底層通過字節(jié)碼處理框架ASM來轉(zhuǎn)換字節(jié)碼并生成新的類末早。
在內(nèi)存中動態(tài)構(gòu)建子類,注意代理的類不能為final说庭,否則報(bào)錯然磷。
- 目標(biāo)對象需要實(shí)現(xiàn)接口:JDK動態(tài)代理
- 目標(biāo)對象不需要實(shí)現(xiàn)接口:Cglib動態(tài)代理
使用示例:
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class ProxyFactory implements MethodInterceptor {
// 傳入被代理對象
Object obj;
public ProxyFactory(Object target) {
this.obj = target;
}
public Object getProxyObj(){
//1.創(chuàng)建一個工具類
Enhancer enhancer = new Enhancer();
//2.設(shè)置父類
enhancer.setSuperclass(obj.getClass());
//3.設(shè)置回調(diào)函數(shù)
enhancer.setCallback(this);
//4.創(chuàng)建子類對象,即代理對象
return enhancer.create();
}
//重寫intercept方法,調(diào)用目標(biāo)對象的方法
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("Cglib代理開始");
Object returnVal=method.invoke(obj,args);
System.out.println("Cglib代理提交");
return returnVal;
}
}