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)方法記錄下來,日后時(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)類不存在接口,則無法使用該方式實(shí)現(xiàn)。
對(duì)于沒有接口的類,要為其創(chuàng)建動(dòng)態(tài)代理,就要使用CGLIB來實(shí)現(xiàn)。CGLIB動(dòng)態(tài)代理的生成原理是生成目標(biāo)類的子類,而子類是增強(qiáng)過的,這個(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管道piped輸入流與輸出流應(yīng)用場(chǎng)景案例分析
這篇文章主要介紹了java管道流PipedInputStream與PipedOutputStream(輸入流與輸出流)的應(yīng)用場(chǎng)景案例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-02-02springboot+RabbitMQ+InfluxDB+Grafara監(jiān)控實(shí)踐
這篇文章主要介紹了springboot+RabbitMQ+InfluxDB+Grafara監(jiān)控實(shí)踐,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-07-07Java實(shí)現(xiàn)讀取項(xiàng)目中文件(.json或.properties)的方法詳解
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)讀取項(xiàng)目中文件的方法,例如.json或.properties,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-04-04Nacos1.4.0 Windows10單機(jī)模式啟動(dòng)和集群?jiǎn)?dòng)過程解析
這篇文章主要介紹了Nacos1.4.0 Windows10單機(jī)模式啟動(dòng)和集群?jiǎn)?dòng),第一次使用nacos,廢話不多說,記錄下自己?jiǎn)?dòng)Nacos遇到的坑,感興趣的朋友跟隨小編一起看看吧2023-10-10