Java中的動態(tài)代理實現(xiàn)代碼實例
一、JDK動態(tài)代理
jdk動態(tài)代理本質上是使用被代理對象的類加載器,通過被代理類實現(xiàn)的接口在運行時動態(tài)構造出代理類來增強原始類的功能的方法,需要使用Java的反射機制,通過實現(xiàn)InvocationHandler接口實現(xiàn)JDK動態(tài)代理。
1、先定義一個接口
package com.teriste.fanshe; public interface HelloWorld { void sayHello(String name); }
2、定義被代理類
該類實現(xiàn)了接口
package com.teriste.fanshe; public class HelloWorldImpl implements HelloWorld { @Override public void sayHello(String name) { System.out.println("Hello "+name); } }
3、定義代理類
實現(xiàn)InvocationHandler接口
package com.teriste.fanshe; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * JDK動態(tài)代理 * 代理類必須實現(xiàn)了接口 */ public class JdkProxyHandler implements InvocationHandler { //被代理的真實對象 private Object target = null; /** * 建立代理對象和真實對象的代理關系,并返回代理對象 * @param target 真實對象 * @return 代理對象 */ public Object bind(Object target){ this.target = target; //真實對象的類加載器 真實對象實現(xiàn)的接口 實現(xiàn)方法邏輯的代理類 return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } /** * 代理方法邏輯 * @param proxy 代理對象 * @param method 真實對象被調用的方法 * @param args 方法入?yún)? * @return 代理結果返回 * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("進入代理邏輯方法"); System.out.println("在調度真實對象前的服務"); Object object = method.invoke(target,args); System.out.println("在調度真實對象后的服務"); return object; } public static void main(String[] args) { JdkProxyHandler jdkProxyHandler = new JdkProxyHandler(); //通過真實對象和代理對象綁定,返回一個代理對象,這個對象和真實對象實現(xiàn)了相同的接口 HelloWorld helloWorld = (HelloWorld) jdkProxyHandler.bind(new HelloWorldImpl()); //該接口調用的方法就是代理對象的invoke方法 helloWorld.sayHello("張三"); } }
二、CGLIB動態(tài)代理
CGLIB動態(tài)代理是通過生成被代理類的子類來增強被代理類功能的方法,因此被代理類必須可以繼承。
1、創(chuàng)建被代理類
package com.teriste.fanshe; import java.lang.reflect.Method; public class ReflectServiceImpl { public void sayHello(String name){ System.out.println("Hello "+name); } public static void main(String[] args) { ReflectServiceImpl target = null; try { target = (ReflectServiceImpl)Class.forName("com.teriste.fanshe.ReflectServiceImpl").newInstance(); Method method = target.getClass().getMethod("sayHello",String.class); method.invoke(target,"張三"); }catch (NoSuchMethodException | ClassNotFoundException e){ e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } }
2、創(chuàng)建代理類
實現(xiàn)MethodInterceptor接口
package com.teriste.fanshe; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * cglib動態(tài)代理 * 代理類必須可以繼承 * 無法代理靜態(tài)方法,需要使用asm修改字節(jié)碼的靜態(tài)代理方式 */ public class CglibProxy implements MethodInterceptor{ /** * 生成CGLIB動態(tài)代理對象 * @param cls 被代理類的CLASS類 * @return 類的CGLIB代理對象 */ public Object getProxy(Class cls){ //CGLIB enhancer 增強類對象 Enhancer enhancer = new Enhancer(); //設置增強類型 enhancer.setSuperclass(cls); //定義代理邏輯對象為當前對象,當前對象必須實現(xiàn)MethodInterceptor.intercept方法 enhancer.setCallback(this); //生成并返回代理對象 return enhancer.create(); } /** * 代理邏輯方法 * @param o 代理對象 * @param method 被代理類的方法 * @param objects 方法入?yún)? * @param methodProxy 方法代理 * @return 代理邏輯返回 * @throws Throwable */ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("調用真實對象前"); methodProxy.invokeSuper(o,objects); System.out.println("調用真實對象后"); return null; } public static void main(String[] args) { CglibProxy cglibProxy = new CglibProxy(); ReflectServiceImpl reflectService = (ReflectServiceImpl) cglibProxy.getProxy(ReflectServiceImpl.class); reflectService.sayHello("張三"); } }
三、代理類的靜態(tài)方法
cglib雖然可以代理類的方法,但是對于類的靜態(tài)方法卻無效,針對靜態(tài)方法需要使用asm重寫類的字節(jié)碼來實現(xiàn)代理效果。
到此這篇關于Java中的動態(tài)代理實現(xiàn)代碼實例的文章就介紹到這了,更多相關Java動態(tài)代理內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
mybatis如何使用Java8的日期LocalDate和LocalDateTime詳解
這篇文章主要給大家介紹了關于mybatis如何使用Java8的日期LocalDate和LocalDateTime的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。2017-09-09ReentrantReadWriteLock?讀寫鎖分析總結
這篇文章主要介紹了ReentrantReadWriteLock 讀寫鎖分析總結,ReentranReadWriteLock中有兩把鎖,一把讀鎖,一把寫鎖,關于這兩把鎖的介紹,需要的小伙伴可以參考一下2022-05-05