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

