Java動態(tài)代理實現(xiàn)方法小結(jié)
本文實例講述了Java動態(tài)代理實現(xiàn)方法。分享給大家供大家參考,具體如下:
靜態(tài)代理了解的差不多了,但是對于動態(tài)代理理解的還不是很通透,這里先把一些常用的動態(tài)代理實現(xiàn)方法記錄下來,日后時??纯礌幦≡缛杖跁炌?。
1、JDK實現(xiàn)動態(tài)代理
主要使用了Proxy.newProxyInstance()方法,該方法的官方解釋為:返回一個指定接口的代理類實例,該接口可以將方法調(diào)用指派到指定的調(diào)用處理程序。
public interface ISomeService {
String doFirst();
void doSecond();
String doThird();
}
//目標類:代理類要增強的類
public class SomeServiceImpl implements ISomeService {
@Override
public String doFirst() {
return "AAAbbb";
}
@Override
public void doSecond() {
System.out.println("SomeServiceImpl:執(zhí)行doSecond()");
}
@Override
public String doThird() {
return "aaa";
}
}
public class Mytest {
public static void main(String[] args) {
ISomeService target = new SomeServiceImpl();
ISomeService someService = (ISomeService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
// proxy:代理對象
// method:目標方法
// args:目標方法的參數(shù)列表
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(target, args);
if(result!=null) {
result=((String)result).toUpperCase();
}
return result;
}
});
System.out.println(someService.doFirst());
someService.doSecond();
System.out.println(someService.doThird());
}
}
2、CGLIB實現(xiàn)動態(tài)代理(沒接口)
使用JDK的Proxy實現(xiàn)動態(tài)代理,要求目標類與代理類實現(xiàn)相同的接口,若目標類不存在接口,則無法使用該方式實現(xiàn)。
對于沒有接口的類,要為其創(chuàng)建動態(tài)代理,就要使用CGLIB來實現(xiàn)。CGLIB動態(tài)代理的生成原理是生成目標類的子類,而子類是增強過的,這個子類對象就是代理對象。使用CGLIB生成代理類,要求目標類必須能被繼承,因此不能是final類。
//目標類:代理類要增強的類
public class SomeService {
public String doFirst() {
System.out.println("SomeServiceImpl:執(zhí)行doFirst()");
return "AAAbbb";
}
public void doSecond() {
System.out.println("SomeServiceImpl:執(zhí)行doSecond()");
}
}
//注意:使用Cglib動態(tài)代理,要求目標類不能是final的
//Cglib動態(tài)代理的增強原理是:子類增強父類,所以目標類必須能被繼承
public class CglibFactory implements MethodInterceptor {
private SomeService target;
public CglibFactory() { }
public CglibFactory(SomeService target) {
this.target = target;
}
public SomeService myCglibCreator() {
Enhancer enhancer = new Enhancer();
//指定父類,即目標類。因為Cglib動態(tài)代理增強的原理是:子類增強父類
enhancer.setSuperclass(SomeService.class);
//設(shè)置回調(diào)接口對象
enhancer.setCallback(this);
//create()方法用于創(chuàng)建Cglib動態(tài)代理對象
return (SomeService)enhancer.create();
}
//回調(diào)函數(shù)的執(zhí)行條件:代理對象執(zhí)行目標方法時會觸發(fā)該方法
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object invoke = method.invoke(target, args);
if(invoke!=null) {
invoke=((String)invoke).toUpperCase();
}
return invoke;
}
}
public class Mytest {
public static void main(String[] args) {
SomeService target = new SomeService();
SomeService proxy = new CglibFactory(target).myCglibCreator();
proxy.doFirst();
}
}
3、CGLIB實現(xiàn)動態(tài)代理(有接口)
在有接口的情況下利用CGLIB實現(xiàn)動態(tài)代理跟沒有接口的情況下利用CGLIB實現(xiàn)動態(tài)代理,其實差不多。
public interface ISomeService {
String doFirst();
void doSecond();
String doThird();
}
//目標類:代理類要增強的類
public class SomeService implements ISomeService {
public String doFirst() {
return "AAAbbb";
}
public void doSecond() {
System.out.println("SomeServiceImpl:執(zhí)行doSecond()");
}
@Override
public String doThird() {
return "third";
}
}
//注意:使用Cglib動態(tài)代理,要求目標類不能是final的
//Cglib動態(tài)代理的增強原理是:子類增強父類,所以目標類必須能被繼承
public class CglibFactory implements MethodInterceptor {
private ISomeService target;
public CglibFactory() { }
public CglibFactory(ISomeService target) {
this.target = target;
}
public ISomeService myCglibCreator() {
Enhancer enhancer = new Enhancer();
//指定父類,即目標類。因為Cglib動態(tài)代理增強的原理是:子類增強父類
enhancer.setSuperclass(ISomeService.class);
//設(shè)置回調(diào)接口對象
enhancer.setCallback(this);
//create()方法用于創(chuàng)建Cglib動態(tài)代理對象
return (ISomeService)enhancer.create();
}
//回調(diào)函數(shù)的執(zhí)行條件:代理對象執(zhí)行目標方法時會觸發(fā)該方法
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object invoke = method.invoke(target, args);
if(invoke!=null) {
invoke=((String)invoke).toUpperCase();
}
return invoke;
}
}
public class Mytest {
public static void main(String[] args) {
ISomeService target = new SomeService();
ISomeService proxy = new CglibFactory(target).myCglibCreator();
System.out.println(proxy.doFirst());
proxy.doSecond();
System.out.println(proxy.doThird());
}
}
更多java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java面向?qū)ο蟪绦蛟O(shè)計入門與進階教程》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設(shè)計有所幫助。
相關(guān)文章
在Java中將List轉(zhuǎn)換為String輸出過程解析
這篇文章主要介紹了在Java中將List轉(zhuǎn)換為String輸出過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友可以參考下2019-09-09
Springboot通過谷歌Kaptcha?組件生成圖形驗證碼功能
Kaptcha是谷歌開源的一款簡單實用的圖形驗證碼組件。我個人推薦它的最大原因是容易上手,采用約定大于配置的方式,快速契合到項目中,這篇文章主要介紹了Springboot通過谷歌Kaptcha組件生成圖形驗證碼的方法,需要的朋友可以參考下2023-05-05
Java中的HttpServletRequest接口詳細解讀
這篇文章主要介紹了Java中的HttpServletRequest接口詳細解讀,是一個接口,全限定名稱為Jakarta.Serclet.http.HttpServletRequest2023-11-11
HttpServletRequest接口是Servlet規(guī)范的一員,需要的朋友可以參考下

