Java動態(tài)代理的兩種實現(xiàn)方式詳解【附相關jar文件下載】
本文實例講述了Java動態(tài)代理的兩種實現(xiàn)方式。分享給大家供大家參考,具體如下:
一說到動態(tài)代理,我們第一個想到肯定是大名鼎鼎的Spring AOP了。在AOP的源碼中用到了兩種動態(tài)代理來實現(xiàn)攔截切入功能:jdk動態(tài)代理和cglib動態(tài)代理。兩種方法同時存在,各有優(yōu)劣。jdk動態(tài)代理是由java內(nèi)部的反射機制來實現(xiàn)的,cglib動態(tài)代理是通過繼承來實現(xiàn)的,底層則是借助asm(Java 字節(jié)碼操控框架)來實現(xiàn)的(采用字節(jié)碼的方式,給A類創(chuàng)建一個子類B,子類B使用方法攔截的技術(shù)攔截所以父類的方法調(diào)用)。總的來說,反射機制在生成類的過程中比較高效,而asm在生成類之后的相關執(zhí)行過程中比較高效(可以通過將asm生成的類進行緩存,這樣解決asm生成類過程低效問題)。還有一點必須注意:jdk動態(tài)代理的應用前提,必須是目標類基于統(tǒng)一的接口。如果沒有上述前提,jdk動態(tài)代理不能應用。由此可以看出,jdk動態(tài)代理有一定的局限性,cglib這種第三方類庫實現(xiàn)的動態(tài)代理應用更加廣泛,且在效率上更有優(yōu)勢。。
公用的接口和實現(xiàn)類
public interface UserService {
public String getName(int id);
public Integer getAge(int id);
}
public class UserServiceImpl implements UserService {
@Override
public String getName(int id) {
System.out.println("------getName------");
return "Tom";
}
@Override
public Integer getAge(int id) {
System.out.println("------getAge------");
return 10;
}
}
JDK的動態(tài)代理實現(xiàn)
jdk的動態(tài)代理,依賴的是反射包下的invocationHandler接口,我們的代理類實現(xiàn)invocationHandler,重寫invoke()方法,每當我們的代理類調(diào)用方法時,都會默認先經(jīng)過invoke()方法。
public class UserInvocationHandler implements InvocationHandler {
private Object target;
UserInvocationHandler() {
super();
}
UserInvocationHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
if("getName".equals(method.getName())){
System.out.println("++++++before " + method.getName() + "++++++");
Object result = method.invoke(target, args);
System.out.println("++++++after " + method.getName() + "++++++");
return result;
}else{
Object result = method.invoke(target, args);
return result;
}
}
}
測試類
public class M {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
InvocationHandler invocationHandler = new UserInvocationHandler(userService);
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(
userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),
invocationHandler);
System.out.println(userServiceProxy.getName(1));
System.out.println(userServiceProxy.getAge(1));
}
}
測試效果

CGLIB的動態(tài)代理實現(xiàn)
cglib依賴的是cglib包下的methodInterceptor接口,每調(diào)用代理類的方法,都會調(diào)用intercept方法
public class CglibMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("------before " + methodProxy.getSuperName() + "------");
Object o1 = methodProxy.invokeSuper(o, args);
System.out.println("------after " + methodProxy.getSuperName() + "------");
return o1;
}
}
測試類
public class M {
public static void main(String[] args) {
CglibMethodInterceptor cglibProxy = new CglibMethodInterceptor();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserServiceImpl.class);
enhancer.setCallback(cglibProxy);
UserService o = (UserService) enhancer.create();
o.getName(1);
o.getAge(1);
}
}
測試結(jié)果

ps:cglib的動態(tài)代理,需要cglib.jar和asm.jar支持
附:點擊此處本站下載 cglib.jar asm.jar 。
更多關于java算法相關內(nèi)容感興趣的讀者可查看本站專題:《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設計有所幫助。
- 詳解Java JDK動態(tài)代理
- 詳解Java Cglib動態(tài)代理
- Java簡單實現(xiàn)動態(tài)代理模式過程解析
- Java JDK動態(tài)代理實現(xiàn)原理實例解析
- 詳細分析java 動態(tài)代理
- Java使用JDK與Cglib動態(tài)代理技術(shù)統(tǒng)一管理日志記錄
- Java動態(tài)代理語法Proxy類原理詳解
- Java代理模式實例詳解【靜態(tài)代理與動態(tài)代理】
- JAVA使用動態(tài)代理對象進行敏感字過濾代碼實例
- 詳解JAVA動態(tài)代理
- Java動態(tài)代理和反射機制詳解
- Java兩種方式實現(xiàn)動態(tài)代理
相關文章
詳解快速排序算法中的區(qū)間劃分法及Java實現(xiàn)示例
這篇文章主要介紹了詳解快速排序算法中的區(qū)間劃分法及Java實現(xiàn)示例,文中分別介紹了快排時兩種區(qū)間劃分的思路,需要的朋友可以參考下2016-04-04
SpringBoot+微信小程序?qū)崿F(xiàn)文件上傳與下載功能詳解
這篇文章主要為大家介紹了SpringBoot整合微信小程序?qū)崿F(xiàn)文件上傳與下載功能,文中的實現(xiàn)步驟講解詳細,快跟隨小編一起學習一下吧2022-03-03
Mybatis MapperScannerConfigurer自動掃描Mapper接口生成代理注入到Spring的方法
這篇文章主要給大家介紹了關于Mybatis MapperScannerConfigurer自動掃描將Mapper接口生成代理注入到Spring的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下2019-03-03

