代理分為靜態(tài)代理和動(dòng)態(tài)代理
? ?按照代理創(chuàng)建的時(shí)期,可以分為靜態(tài)代理和動(dòng)態(tài)代理:
? ? (1) 靜態(tài)代理:由程序員或者自動(dòng)生成工具生成代理類,然后進(jìn)行代理類的編譯和運(yùn)行。在代理類、委托類運(yùn)行之前,代理類已經(jīng)以.class的格式存在。
? ? (2)動(dòng)態(tài)代理:在程序運(yùn)行時(shí),由反射機(jī)制動(dòng)態(tài)創(chuàng)建而成。
? ? (3)JDK的動(dòng)態(tài)代理機(jī)制只能代理實(shí)現(xiàn)了接口的類,而不能實(shí)現(xiàn)接口的類就不能實(shí)現(xiàn)JDK的動(dòng)態(tài)代理,cglib是針對(duì)類來實(shí)現(xiàn)代理的,他的原理是對(duì)指定的目標(biāo)類生成一個(gè)子類,并覆蓋其中方法實(shí)現(xiàn)增強(qiáng),但因?yàn)椴捎玫氖抢^承,所以不能對(duì)final修飾的類進(jìn)行代理。
代理方式實(shí)現(xiàn)優(yōu)點(diǎn)缺點(diǎn)特點(diǎn)
JDK靜態(tài)代理代理類與委托類實(shí)現(xiàn)同一接口,并且在代理類中需要硬編碼接口實(shí)現(xiàn)簡單,容易理解代理類需要硬編碼接口,在實(shí)際應(yīng)用中可能會(huì)導(dǎo)致重復(fù)編碼,浪費(fèi)存儲(chǔ)空間并且效率很低好像沒啥特點(diǎn)
JDK動(dòng)態(tài)代理代理類與委托類實(shí)現(xiàn)同一接口,主要是通過代理類實(shí)現(xiàn)InvocationHandler并重寫invoke方法來進(jìn)行動(dòng)態(tài)代理的,在invoke方法中將對(duì)方法進(jìn)行增強(qiáng)處理不需要硬編碼接口,代碼復(fù)用率高只能夠代理實(shí)現(xiàn)了接口的委托類底層使用反射機(jī)制進(jìn)行方法的調(diào)用
CGLIB動(dòng)態(tài)代理代理類將委托類作為自己的父類并為其中的非final委托方法創(chuàng)建兩個(gè)方法,一個(gè)是與委托方法簽名相同的方法,它在方法中會(huì)通過super調(diào)用委托方法;另一個(gè)是代理類獨(dú)有的方法。在代理方法中,它會(huì)判斷是否存在實(shí)現(xiàn)了MethodInterceptor接口的對(duì)象,若存在則將調(diào)用intercept方法對(duì)委托方法進(jìn)行代理可以在運(yùn)行時(shí)對(duì)類或者是接口進(jìn)行增強(qiáng)操作,且委托類無需實(shí)現(xiàn)接口不能對(duì)final類以及final方法進(jìn)行代理底層將方法全部存入一個(gè)數(shù)組中,通過數(shù)組索引直接進(jìn)行方法調(diào)用

JDK動(dòng)態(tài)代理
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author chexingyou
* @date 2013-6-6
*/
interface Dao {
void show();
void say();
}
interface Dao2 {
void say();
}
class Imp implements Dao, Dao2 {
public void show() {
System.out.println("do show");
}
public void say() {
System.out.println("do say");
}
}
class Handler implements InvocationHandler {
private Object obj;
public Handler(Object obj) {
this.obj = obj;
}
public static Object create(Object obj) {
return Proxy.newProxyInstance(Imp.class.getClassLoader(), Imp.class.getInterfaces(),
new Handler(obj));
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before " + method.getName());
Object ret = method.invoke(obj, args);
System.out.println("after " + method.getName());
return ret;
}
}
public class Test {
public static void main(String[] args) {
Dao imp = new Imp();
Dao proxy = (Dao) Handler.create(imp);
proxy.show();
proxy.say();
Dao2 proxy2 = (Dao2) Handler.create(imp);
proxy2.say();
}
}
package cglib;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* @author chexingyou
* @date 2013-6-7
*/
class Imp {
public void say() {
System.out.println("say()");
}
}
class CglibProxy implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
throws Throwable {
System.out.println("do before");
Object ret = proxy.invokeSuper(obj, args);
System.out.println("do after");
return ret;
}
public Object getProxy(Class<?> clazz) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
}
public class Test {
public static void main(String[] args) {
CglibProxy proxy = new CglibProxy();
Imp imp = (Imp) proxy.getProxy(Imp.class);
imp.say();
}
}