本文實例講述了Java動態代理的兩種實現方式。分享給大家供大家參考,具體如下:
一說到動態代理,我們第一個想到肯定是大名鼎鼎的Spring AOP了。在AOP的源碼中用到了兩種動態代理來實現攔截切入功能:jdk動態代理和cglib動態代理。兩種方法同時存在,各有優劣。jdk動態代理是由java內部的反射機制來實現的,cglib動態代理是通過繼承來實現的,底層則是借助asm(Java 字節碼操控框架)來實現的(采用字節碼的方式,給A類創建一個子類B,子類B使用方法攔截的技術攔截所以父類的方法調用)??偟膩碚f,反射機制在生成類的過程中比較高效,而asm在生成類之后的相關執行過程中比較高效(可以通過將asm生成的類進行緩存,這樣解決asm生成類過程低效問題)。還有一點必須注意:jdk動態代理的應用前提,必須是目標類基于統一的接口。如果沒有上述前提,jdk動態代理不能應用。由此可以看出,jdk動態代理有一定的局限性,cglib這種第三方類庫實現的動態代理應用更加廣泛,且在效率上更有優勢。。
公用的接口和實現類
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的動態代理實現
jdk的動態代理,依賴的是反射包下的invocationHandler接口,我們的代理類實現invocationHandler,重寫invoke()方法,每當我們的代理類調用方法時,都會默認先經過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的動態代理實現
cglib依賴的是cglib包下的methodInterceptor接口,每調用代理類的方法,都會調用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); }}
測試結果
ps:cglib的動態代理,需要cglib.jar和asm.jar支持
附:點擊此處本站下載 cglib.jar asm.jar 。
希望本文所述對大家java程序設計有所幫助。
新聞熱點
疑難解答
圖片精選