Java動(dòng)態(tài)代理技術(shù)廣泛的應(yīng)用于我們的項(xiàng)目之中把曼,比如Spring AOP排宰、分布式服務(wù)框架等俊鱼。其主要實(shí)現(xiàn)方式有2種,一種是JDK動(dòng)態(tài)代理粟瞬,一種是cglib動(dòng)態(tài)代理,兩種方式各有優(yōu)劣萤捆,本文在此做一個(gè)總結(jié)裙品。
JDK動(dòng)態(tài)代理
JDK自帶的代理機(jī)制
實(shí)現(xiàn)原理:接口俗批,反射。
運(yùn)行時(shí)根據(jù)目標(biāo)類動(dòng)態(tài)創(chuàng)建代理類市怎,代理類和目標(biāo)類實(shí)現(xiàn)相同的接口岁忘。調(diào)用方調(diào)用代理類,代理類反射調(diào)用目標(biāo)類区匠。
優(yōu)點(diǎn):
- 創(chuàng)建代理性能比cglib好
- JDK自帶干像,無需引用第三方包
缺點(diǎn):
- 需要依賴共同的接口,如果目標(biāo)類沒有實(shí)現(xiàn)接口驰弄,就無法代理麻汰。
- 代理類執(zhí)行速度較慢
創(chuàng)建代理流程
- 實(shí)現(xiàn)InvocationHandler接口,創(chuàng)建自己調(diào)用處理器揩懒,主要是實(shí)現(xiàn)invoke方法什乙。invoke方法負(fù)責(zé)正真調(diào)用目標(biāo)類的方法。
- 通Proxy.newProxyInstance()創(chuàng)建代理類已球,需要三個(gè)參數(shù):目標(biāo)類的ClassLoader臣镣、Interfaces和InvocationHandler。
實(shí)例
package com.javastudy.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author fangyi.xfy 2016/8/23 11:29.
*/
public class ProxyFactory implements InvocationHandler {
/**
* 目標(biāo)對(duì)象
*/
private Object target;
/**
* 創(chuàng)建代理類
**/
public Object newProxyInstance(Object target){
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
/**
* 重寫調(diào)用方法智亮,此處可以織入代碼忆某,比如AOP切面
**/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before invoke");
Object res = method.invoke(target, args);
System.out.println("after invoke");
return res;
}
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
ProxyFactory proxyFactory = new ProxyFactory();
UserService proxy = (UserService) proxyFactory.newProxyInstance(userService);
proxy.addUser("Andy");
}
}
參考:
Java JDK 動(dòng)態(tài)代理使用及實(shí)現(xiàn)原理分析
cglib動(dòng)態(tài)代理
cglib - Byte Code Generation Library is high level API to generate and transform Java byte code. It is used by AOP, testing, data access frameworks to generate dynamic proxy objects and intercept field access. https://github.com/cglib/cglib/wiki
實(shí)現(xiàn)原理:繼承,反射阔蛉。
運(yùn)行時(shí)根據(jù)目標(biāo)類動(dòng)態(tài)創(chuàng)建代理類弃舒,代理類是目標(biāo)類的子類。
優(yōu)點(diǎn):
- 執(zhí)行性能優(yōu)于JDK動(dòng)態(tài)代理
缺點(diǎn):
- 由于是繼承状原,無法對(duì)final修飾的class代理
- 創(chuàng)建代理類性能較差
創(chuàng)建代理流程
- 實(shí)現(xiàn)MethodInterceptor接口聋呢,創(chuàng)建自己的方法攔截器,實(shí)現(xiàn)intercept方法颠区。
- 通過Enhancer創(chuàng)建目標(biāo)類的代理削锰,需要目標(biāo)類的class,MethodInterceptor毕莱。
實(shí)例
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz) {
//設(shè)置需要?jiǎng)?chuàng)建子類的類
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通過字節(jié)碼技術(shù)動(dòng)態(tài)創(chuàng)建子類實(shí)例
return enhancer.create();
}
//實(shí)現(xiàn)MethodInterceptor接口方法
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("前置代理");
//通過代理類調(diào)用父類中的方法
Object result = proxy.invokeSuper(obj, args);
System.out.println("后置代理");
return result;
}
}