java中的動態(tài)代理與責任鏈模式詳解
動態(tài)代理
動態(tài)代理是一種設(shè)計模式,它允許在運行時創(chuàng)建代理對象,并將方法調(diào)用重定向到不同的實際對象。
它使我們能夠在不修改現(xiàn)有代碼的情況下增加或改變某個對象的行為。
jdk動態(tài)代理
被代理接口:
package com.mzs.test; public interface DemoService { void speak(String str); void jump(String str); }
被代理類:
package com.mzs.test; public class DemoServiceImpl implements DemoService { public void speak(String string) { System.out.println("hello " + string); } public void jump(String string) { System.out.println("hi " + string); } }
代理類:
package com.mzs.test; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class TestProxy implements InvocationHandler { private Object target; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(target, args); } public Object bind(Object target) { this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } }
測試方法:
package com.mzs.test; public class TestProxyDemo { public static void main(String[] args) { TestProxy instance = new TestProxy(); DemoService proxy = (DemoService) instance.bind(new DemoServiceImpl()); proxy.speak("tom"); } }
cglib動態(tài)代理
被代理的類:
package com.mzs.test; public class DemoServiceImpl { public void speak(String string) { System.out.println("hello " + string); } public void jump(String string) { System.out.println("hi " + string); } }
代理類:
package com.mzs.test; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class TestProxy implements MethodInterceptor { /** * 代理邏輯方法 * * @param o 代理對象 * @param method 方法 * @param objects 方法參數(shù) * @param methodProxy 代理方法 * @return 方法返回值 * @throws Throwable 異常 */ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { return methodProxy.invokeSuper(o, objects); } /** * 生成代理對象 * * @param cls 被代理的Class對象 * @return 代理對象 */ public Object bind(Class cls) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(cls); enhancer.setCallback(this); return enhancer.create(); } }
測試方法:
package com.mzs.test; public class TestProxyDemo { public static void main(String[] args) { TestProxy instance = new TestProxy(); DemoServiceImpl proxy = (DemoServiceImpl) instance.bind(DemoServiceImpl.class); proxy.jump("tom"); proxy.speak("selina"); } }
注:導(dǎo)入的依賴,如下:
<!-- cglib proxy --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>asm</groupId> <artifactId>asm</artifactId> <version>3.3</version> </dependency>
兩者的特點
- jdk動態(tài)代理,使用反射生成實現(xiàn)接口的代理類,被代理類需要實現(xiàn)接口,效率比jdk動態(tài)代理高。
- cglib動態(tài)代理,使用asm字節(jié)技術(shù)生成代理類,繼承被代理類,并覆蓋并加強父類的方法。
責任鏈模式
package com.mzs.testThread1; public interface UserService { void speak(String str); } package com.mzs.testThread1; public class UserServiceImpl implements UserService { @Override public void speak(String str) { System.out.println(str); } }
MyInterceptor2、MyInterceptor3都一樣: (除了1變成2或者3)
package com.mzs.testThread1; import java.lang.reflect.Method; public class MyInterceptor implements Interceptor { @Override public boolean before(Object proxy, Object target, Method method, Object[] args) { System.out.println("反射方法前邏輯1"); return true; } @Override public void around(Object proxy, Object target, Method method, Object[] args) { System.out.println("取代被代理對象的方法"); } @Override public void after(Object proxy, Object target, Method method, Object[] args) { System.out.println("反射方法后邏輯1"); } }
package com.mzs.testThread1; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class InterceptorProxy implements InvocationHandler { private Object target; private Interceptor interceptor; public InterceptorProxy(Object target, Interceptor interceptor) { this.target = target; this.interceptor = interceptor; } public static Object bind(Object target, Interceptor interceptor) { return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InterceptorProxy(target, interceptor)); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; if (interceptor == null) result = method.invoke(target, args); if (interceptor.before(proxy, target, method, args)) result = method.invoke(target, args); else interceptor.around(proxy, target, method, args); interceptor.after(proxy, target, method, args); return result; } }
測試方法:
package com.mzs.testThread1; public class TestDemo { public static void main(String[] args) { UserService proxy1 = (UserService) InterceptorProxy.bind(new UserServiceImpl(), new MyInterceptor()); UserService proxy2 = (UserService) InterceptorProxy.bind(proxy1, new MyInterceptor2()); UserService proxy3 = (UserService) InterceptorProxy.bind(proxy2, new MyInterceptor3()); proxy3.speak("hello"); } }
控制臺輸出如下:
反射方法前邏輯3
反射方法前邏輯2
反射方法前邏輯1
hello
反射方法后邏輯1
反射方法后邏輯2
反射方法后邏輯3
到此這篇關(guān)于java中的動態(tài)代理與責任鏈模式詳解的文章就介紹到這了,更多相關(guān)java動態(tài)代理與責任鏈內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Json字符串轉(zhuǎn)Java對象和List代碼實例
這篇文章主要介紹了Json字符串轉(zhuǎn)Java對象和List代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06SpringBoot整合Elasticsearch游標查詢的示例代碼(scroll)
這篇文章主要介紹了SpringBoot整合Elasticsearch游標查詢(scroll),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-10-10