java中的動態(tài)代理與責(zé)任鏈模式詳解
動態(tài)代理
動態(tài)代理是一種設(shè)計(jì)模式,它允許在運(yùn)行時創(chuàng)建代理對象,并將方法調(diào)用重定向到不同的實(shí)際對象。
它使我們能夠在不修改現(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>
兩者的特點(diǎn)
- jdk動態(tài)代理,使用反射生成實(shí)現(xiàn)接口的代理類,被代理類需要實(shí)現(xiàn)接口,效率比jdk動態(tài)代理高。
- cglib動態(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都一樣: (除了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)代理與責(zé)任鏈模式詳解的文章就介紹到這了,更多相關(guān)java動態(tài)代理與責(zé)任鏈內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用JDBC實(shí)現(xiàn)數(shù)據(jù)訪問對象層(DAO)代碼示例
這篇文章主要介紹了使用JDBC實(shí)現(xiàn)數(shù)據(jù)訪問對象層(DAO)代碼示例,具有一定參考價值,需要的朋友可以了解下。2017-10-10
通過Java連接SQL?Server數(shù)據(jù)庫的超詳細(xì)操作流程
java相對于其他語言(例如c,c++等)連接數(shù)據(jù)庫要方便得多,那么如何連接呢?下面這篇文章主要給大家介紹了關(guān)于通過Java連接SQL?Server數(shù)據(jù)庫的超詳細(xì)操作流程,需要的朋友可以參考下2023-03-03
Mybatis-Plus通過配置在控制臺打印執(zhí)行日志的實(shí)現(xiàn)
本文主要介紹了Mybatis-Plus通過配置在控制臺打印執(zhí)行日志的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-04-04
Java實(shí)現(xiàn)一鍵獲取Mysql所有表字段設(shè)計(jì)和建表語句的工具類
這篇文章主要為大家詳細(xì)介紹了如何利用Java編寫一個工具類,可以實(shí)現(xiàn)一鍵獲取Mysql所有表字段設(shè)計(jì)和建表語句,感興趣的小伙伴可以了解一下2023-05-05
詳解 maven的pom.xml用<exclusion>解決版本問題
這篇文章主要介紹了詳解 maven的pom.xml用<exclusion>解決版本問題的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下2017-09-09
Mybatis批量插入數(shù)據(jù)的兩種方式總結(jié)與對比
批量插入功能是我們?nèi)粘9ぷ髦斜容^常見的業(yè)務(wù)功能之一,下面這篇文章主要給大家介紹了關(guān)于Mybatis批量插入數(shù)據(jù)的兩種方式總結(jié)與對比的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01

