Java動(dòng)態(tài)代理實(shí)現(xiàn)方法小結(jié)
本文實(shí)例講述了Java動(dòng)態(tài)代理實(shí)現(xiàn)方法。分享給大家供大家參考,具體如下:
靜態(tài)代理了解的差不多了,但是對(duì)于動(dòng)態(tài)代理理解的還不是很通透,這里先把一些常用的動(dòng)態(tài)代理實(shí)現(xiàn)方法記錄下來(lái),日后時(shí)常看看爭(zhēng)取早日融會(huì)貫通。
1、JDK實(shí)現(xiàn)動(dòng)態(tài)代理
主要使用了Proxy.newProxyInstance()方法,該方法的官方解釋為:返回一個(gè)指定接口的代理類實(shí)例,該接口可以將方法調(diào)用指派到指定的調(diào)用處理程序。
public interface ISomeService {
String doFirst();
void doSecond();
String doThird();
}
//目標(biāo)類:代理類要增強(qiáng)的類
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:代理對(duì)象
// method:目標(biāo)方法
// args:目標(biāo)方法的參數(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實(shí)現(xiàn)動(dòng)態(tài)代理(沒接口)
使用JDK的Proxy實(shí)現(xiàn)動(dòng)態(tài)代理,要求目標(biāo)類與代理類實(shí)現(xiàn)相同的接口,若目標(biāo)類不存在接口,則無(wú)法使用該方式實(shí)現(xiàn)。
對(duì)于沒有接口的類,要為其創(chuàng)建動(dòng)態(tài)代理,就要使用CGLIB來(lái)實(shí)現(xiàn)。CGLIB動(dòng)態(tài)代理的生成原理是生成目標(biāo)類的子類,而子類是增強(qiáng)過(guò)的,這個(gè)子類對(duì)象就是代理對(duì)象。使用CGLIB生成代理類,要求目標(biāo)類必須能被繼承,因此不能是final類。
//目標(biāo)類:代理類要增強(qiáng)的類
public class SomeService {
public String doFirst() {
System.out.println("SomeServiceImpl:執(zhí)行doFirst()");
return "AAAbbb";
}
public void doSecond() {
System.out.println("SomeServiceImpl:執(zhí)行doSecond()");
}
}
//注意:使用Cglib動(dòng)態(tài)代理,要求目標(biāo)類不能是final的
//Cglib動(dòng)態(tài)代理的增強(qiáng)原理是:子類增強(qiáng)父類,所以目標(biāo)類必須能被繼承
public class CglibFactory implements MethodInterceptor {
private SomeService target;
public CglibFactory() { }
public CglibFactory(SomeService target) {
this.target = target;
}
public SomeService myCglibCreator() {
Enhancer enhancer = new Enhancer();
//指定父類,即目標(biāo)類。因?yàn)镃glib動(dòng)態(tài)代理增強(qiáng)的原理是:子類增強(qiáng)父類
enhancer.setSuperclass(SomeService.class);
//設(shè)置回調(diào)接口對(duì)象
enhancer.setCallback(this);
//create()方法用于創(chuàng)建Cglib動(dòng)態(tài)代理對(duì)象
return (SomeService)enhancer.create();
}
//回調(diào)函數(shù)的執(zhí)行條件:代理對(duì)象執(zhí)行目標(biāo)方法時(shí)會(huì)觸發(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實(shí)現(xiàn)動(dòng)態(tài)代理(有接口)
在有接口的情況下利用CGLIB實(shí)現(xiàn)動(dòng)態(tài)代理跟沒有接口的情況下利用CGLIB實(shí)現(xiàn)動(dòng)態(tài)代理,其實(shí)差不多。
public interface ISomeService {
String doFirst();
void doSecond();
String doThird();
}
//目標(biāo)類:代理類要增強(qiáng)的類
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動(dòng)態(tài)代理,要求目標(biāo)類不能是final的
//Cglib動(dòng)態(tài)代理的增強(qiáng)原理是:子類增強(qiáng)父類,所以目標(biāo)類必須能被繼承
public class CglibFactory implements MethodInterceptor {
private ISomeService target;
public CglibFactory() { }
public CglibFactory(ISomeService target) {
this.target = target;
}
public ISomeService myCglibCreator() {
Enhancer enhancer = new Enhancer();
//指定父類,即目標(biāo)類。因?yàn)镃glib動(dòng)態(tài)代理增強(qiáng)的原理是:子類增強(qiáng)父類
enhancer.setSuperclass(ISomeService.class);
//設(shè)置回調(diào)接口對(duì)象
enhancer.setCallback(this);
//create()方法用于創(chuàng)建Cglib動(dòng)態(tài)代理對(duì)象
return (ISomeService)enhancer.create();
}
//回調(diào)函數(shù)的執(zhí)行條件:代理對(duì)象執(zhí)行目標(biāo)方法時(shí)會(huì)觸發(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è)計(jì)入門與進(jìn)階教程》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。
相關(guān)文章
java實(shí)現(xiàn)簡(jiǎn)單驗(yàn)證碼生成
這篇文章主要介紹了java實(shí)現(xiàn)簡(jiǎn)單驗(yàn)證碼生成,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10
在Java中將List轉(zhuǎn)換為String輸出過(guò)程解析
這篇文章主要介紹了在Java中將List轉(zhuǎn)換為String輸出過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
SpringBoot實(shí)戰(zhàn)教程之新手入門篇
Spring Boot使我們更容易去創(chuàng)建基于Spring的獨(dú)立和產(chǎn)品級(jí)的可以"即時(shí)運(yùn)行"的應(yīng)用和服務(wù),下面這篇文章主要給大家介紹了關(guān)于SpringBoot實(shí)戰(zhàn)教程之入門篇的相關(guān)資料,需要的朋友可以參考下2022-03-03
Springboot通過(guò)谷歌Kaptcha?組件生成圖形驗(yàn)證碼功能
Kaptcha是谷歌開源的一款簡(jiǎn)單實(shí)用的圖形驗(yàn)證碼組件。我個(gè)人推薦它的最大原因是容易上手,采用約定大于配置的方式,快速契合到項(xiàng)目中,這篇文章主要介紹了Springboot通過(guò)谷歌Kaptcha組件生成圖形驗(yàn)證碼的方法,需要的朋友可以參考下2023-05-05
Java中的HttpServletRequest接口詳細(xì)解讀
這篇文章主要介紹了Java中的HttpServletRequest接口詳細(xì)解讀,是一個(gè)接口,全限定名稱為Jakarta.Serclet.http.HttpServletRequest2023-11-11
HttpServletRequest接口是Servlet規(guī)范的一員,需要的朋友可以參考下

