java中的動(dòng)態(tài)代理與責(zé)任鏈模式詳解
動(dòng)態(tài)代理
動(dòng)態(tài)代理是一種設(shè)計(jì)模式,它允許在運(yùn)行時(shí)創(chuàng)建代理對(duì)象,并將方法調(diào)用重定向到不同的實(shí)際對(duì)象。
它使我們能夠在不修改現(xiàn)有代碼的情況下增加或改變某個(gè)對(duì)象的行為。
jdk動(dòng)態(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動(dòng)態(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 代理對(duì)象 * @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); } /** * 生成代理對(duì)象 * * @param cls 被代理的Class對(duì)象 * @return 代理對(duì)象 */ 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>
兩者的特點(diǎn)
- jdk動(dòng)態(tài)代理,使用反射生成實(shí)現(xiàn)接口的代理類,被代理類需要實(shí)現(xiàn)接口,效率比jdk動(dòng)態(tài)代理高。
- cglib動(dòng)態(tài)代理,使用asm字節(jié)技術(shù)生成代理類,繼承被代理類,并覆蓋并加強(qiáng)父類的方法。
責(zé)任鏈模式
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都一樣:?。ǔ?變成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("取代被代理對(duì)象的方法"); } @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"); } }
控制臺(tái)輸出如下:
反射方法前邏輯3
反射方法前邏輯2
反射方法前邏輯1
hello
反射方法后邏輯1
反射方法后邏輯2
反射方法后邏輯3
到此這篇關(guān)于java中的動(dòng)態(tài)代理與責(zé)任鏈模式詳解的文章就介紹到這了,更多相關(guān)java動(dòng)態(tài)代理與責(zé)任鏈內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Json字符串轉(zhuǎn)Java對(duì)象和List代碼實(shí)例
這篇文章主要介紹了Json字符串轉(zhuǎn)Java對(duì)象和List代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06SpringBoot自動(dòng)配置與啟動(dòng)流程詳細(xì)分析
這篇文章主要介紹了SpringBoot自動(dòng)配置原理分析,SpringBoot是我們經(jīng)常使用的框架,那么你能不能針對(duì)SpringBoot實(shí)現(xiàn)自動(dòng)配置做一個(gè)詳細(xì)的介紹。如果可以的話,能不能畫一下實(shí)現(xiàn)自動(dòng)配置的流程圖。牽扯到哪些關(guān)鍵類,以及哪些關(guān)鍵點(diǎn)2022-11-11SpringBoot整合Elasticsearch游標(biāo)查詢的示例代碼(scroll)
這篇文章主要介紹了SpringBoot整合Elasticsearch游標(biāo)查詢(scroll),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10