動(dòng)態(tài)代理的描述在前兩篇文章已經(jīng)做了一部分描述動(dòng)態(tài)代理的詳細(xì)解讀和動(dòng)態(tài)代理的簡(jiǎn)單描述,JDK的動(dòng)態(tài)代理只能針對(duì)實(shí)現(xiàn)了接口的類(lèi)生成代理拒垃。而cglib的動(dòng)態(tài)代理是針對(duì)類(lèi)實(shí)現(xiàn)代理停撞,這兩種代理我們可以靈活使用。我們通過(guò)汽車(chē)跑的例子來(lái)解讀這兩種動(dòng)態(tài)代理悼瓮。
一.JDK動(dòng)態(tài)代理
Car接口
package proxy;
public interface Car {
public void run();
}
Car實(shí)現(xiàn)類(lèi)
package proxy;
public class CarImpl implements Car{
public void run() {
System.out.println("car running");
}
}
Car代理類(lèi)
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//JDK動(dòng)態(tài)代理代理類(lèi)
public class CarHandler implements InvocationHandler{
//真實(shí)類(lèi)的對(duì)象
private Object car;
//構(gòu)造方法賦值給真實(shí)的類(lèi)
public CarHandler(Object obj){
this.car = obj;
}
//代理類(lèi)執(zhí)行方法時(shí)戈毒,調(diào)用的是這個(gè)方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object res = method.invoke(car, args);
System.out.println("after");
return res;
}
}
main方法
package proxy;
import java.lang.reflect.Proxy;
public class main {
public static void main(String[] args) {
CarImpl carImpl = new CarImpl();
CarHandler carHandler = new CarHandler(carImpl);
Car proxy = (Car)Proxy.newProxyInstance(
main.class.getClassLoader(), //第一個(gè)參數(shù),獲取ClassLoader
carImpl.getClass().getInterfaces(), //第二個(gè)參數(shù)横堡,獲取被代理類(lèi)的接口
carHandler);//第三個(gè)參數(shù)埋市,一個(gè)InvocationHandler對(duì)象,表示的是當(dāng)我這個(gè)動(dòng)態(tài)代理對(duì)象在調(diào)用方法的時(shí)候命贴,會(huì)關(guān)聯(lián)到哪一個(gè)InvocationHandler對(duì)象上
proxy.run();
}
}
運(yùn)行結(jié)果
before
car running
after
通過(guò)上面的例子三個(gè)參數(shù)我們可以看到道宅,JDK的動(dòng)態(tài)代理依靠接口實(shí)現(xiàn),入?yún)⒈仨氂斜淮眍?lèi)的接口胸蛛,也就是
carImpl.getClass().getInterfaces()
,如果有些類(lèi)并沒(méi)有實(shí)現(xiàn)接口污茵,則不能使用JDK代理,這就要使用cglib動(dòng)態(tài)代理了葬项。
二.Cglib動(dòng)態(tài)代理
沒(méi)有實(shí)現(xiàn)接口的Car
package proxy;
public class CarNoInterface {
public void run() {
System.out.println("car running");
}
}
cglib代理類(lèi)
package proxy;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor{
private Object car;
/**
* 創(chuàng)建代理對(duì)象
*
* @param target
* @return
*/
public Object getInstance(Object object) {
this.car = object;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.car.getClass());
// 回調(diào)方法
enhancer.setCallback(this);
// 創(chuàng)建代理對(duì)象
return enhancer.create();
}
@Override
public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {
System.out.println("事物開(kāi)始");
proxy.invokeSuper(obj, args);
System.out.println("事物結(jié)束");
return null;
}
}
main方法
package proxy;
import java.lang.reflect.Proxy;
public class main {
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
CarNoInterface carNoInterface = (CarNoInterface)cglibProxy.getInstance(new CarNoInterface());
carNoInterface.run();
}
}
結(jié)果輸出
事物開(kāi)始
car running
事物結(jié)束
上面兩個(gè)例子我們已經(jīng)看到這兩種動(dòng)態(tài)代理各自的分工了泞当,在實(shí)際開(kāi)發(fā)中,可以根據(jù)需求來(lái)靈活安排使用接口來(lái)代理還是類(lèi)來(lái)代理了民珍。