JDK動(dòng)態(tài)代理與CGLib動(dòng)態(tài)代理的區(qū)別對(duì)比
案例:
public interface ForumService { void removeTopic(int topicId); void removeForum(int forumId); }
對(duì)相關(guān)方法進(jìn)行性能監(jiān)控
public class ForumServiceImpl implements ForumService { public void removeTopic(int topicId) { // PerformanceMonitor.begin("com.hand.proxy.ForumServiceImpl.removeTopic"); System.out.println("模擬刪除Topic記錄:" + topicId); try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } // PerformanceMonitor.end(); } public void removeForum(int forumId) { // PerformanceMonitor.begin("com.hand.proxy.ForumServiceImpl.removeForum"); System.out.println("模擬刪除Forum記錄:" + forumId); try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } // PerformanceMonitor.end(); } }
性能監(jiān)控實(shí)現(xiàn)類:
public class PerformanceMonitor { // 通過一個(gè)ThreadLocal保存與調(diào)用線程相關(guān)的性能監(jiān)視信息 private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>(); // 啟動(dòng)對(duì)某一目標(biāo)方法的性能監(jiān)視 public static void begin(String method) { System.out.println("begin monitor..."); MethodPerformance mp = new MethodPerformance(method); performanceRecord.set(mp); } public static void end() { System.out.println("end monitor..."); MethodPerformance mp = performanceRecord.get(); // 打印出方法性能監(jiān)視的結(jié)果信息 mp.printPerformance(); } }
用于記錄性能監(jiān)控信息:
public class PerformanceMonitor { // 通過一個(gè)ThreadLocal保存與調(diào)用線程相關(guān)的性能監(jiān)視信息 private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>(); // 啟動(dòng)對(duì)某一目標(biāo)方法的性能監(jiān)視 public static void begin(String method) { System.out.println("begin monitor..."); MethodPerformance mp = new MethodPerformance(method); performanceRecord.set(mp); } public static void end() { System.out.println("end monitor..."); MethodPerformance mp = performanceRecord.get(); // 打印出方法性能監(jiān)視的結(jié)果信息 mp.printPerformance(); } }
1、JDK動(dòng)態(tài)代理
public class PerformanceMonitor { // 通過一個(gè)ThreadLocal保存與調(diào)用線程相關(guān)的性能監(jiān)視信息 private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>(); // 啟動(dòng)對(duì)某一目標(biāo)方法的性能監(jiān)視 public static void begin(String method) { System.out.println("begin monitor..."); MethodPerformance mp = new MethodPerformance(method); performanceRecord.set(mp); } public static void end() { System.out.println("end monitor..."); MethodPerformance mp = performanceRecord.get(); // 打印出方法性能監(jiān)視的結(jié)果信息 mp.printPerformance(); } }
public class ForumServiceTest { @Test public void proxy() { ForumService forumService = new ForumServiceImpl(); PerformanceHandler handler = new PerformanceHandler(forumService); ForumService proxy = (ForumService) Proxy.newProxyInstance(forumService.getClass().getClassLoader(), forumService.getClass().getInterfaces(), handler); proxy.removeForum(10); proxy.removeTopic(1012); } }
得到以下輸出信息:
begin monitor...
模擬刪除Forum記錄:10
end monitor...
com.hand.proxy.ForumServiceImpl.removeForum花費(fèi)21毫秒
begin monitor...
模擬刪除Topic記錄:1012
end monitor...
com.hand.proxy.ForumServiceImpl.removeTopic花費(fèi)21毫秒
2、CGLib動(dòng)態(tài)代理
<!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency>
public class CglibProxy implements MethodInterceptor { private Enhancer enhancer = new Enhancer(); public Object getProxy(Class clazz) { enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { PerformanceMonitor.begin(obj.getClass().getName() + "." + method.getName()); Object result = proxy.invokeSuper(obj, args); PerformanceMonitor.end(); return result; } }
public class ForumServiceTest2 { @Test public void proxy() { CglibProxy proxy = new CglibProxy(); ForumServiceImpl forumService = (ForumServiceImpl) proxy.getProxy(ForumServiceImpl.class); forumService.removeForum(10); forumService.removeTopic(1023); } }
1)、JDK和CGLib的區(qū)別
- JDK動(dòng)態(tài)代理只能對(duì)實(shí)現(xiàn)了接口的類生成代理,而不能針對(duì)類
- CGLib是針對(duì)類實(shí)現(xiàn)代理,主要是對(duì)指定的類生成一個(gè)子類,覆蓋其中的方法(繼承)
2)、Spring在選擇用JDK還是CGLib的依據(jù)
- 當(dāng)Bean實(shí)現(xiàn)接口時(shí),Spring就會(huì)用JDK的動(dòng)態(tài)代理
- 當(dāng)Bean沒有實(shí)現(xiàn)接口時(shí),Spring使用CGLib來實(shí)現(xiàn)
- 可以強(qiáng)制使用CGLib(在Spring配置中加入<aop:aspectj-autoproxy proxy-target-class=“true”/>)
3)、JDK和CGLib的性能對(duì)比
- 使用CGLib實(shí)現(xiàn)動(dòng)態(tài)代理,CGLib底層采用ASM字節(jié)碼生成框架,使用字節(jié)碼技術(shù)生成代理類,在JDK1.6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能對(duì)聲明為final的方法進(jìn)行代理,因?yàn)镃GLib原理是動(dòng)態(tài)生成被代理類的子類。
- 在JDK1.6、JDK1.7、JDK1.8逐步對(duì)JDK動(dòng)態(tài)代理優(yōu)化之后,在調(diào)用次數(shù)較少的情況下,JDK代理效率高于CGLib代理效率,只有當(dāng)進(jìn)行大量調(diào)用的時(shí)候,JDK1.6和JDK1.7比CGLib代理效率低一點(diǎn),但是到JDK1.8的時(shí)候,JDK代理效率高于CGLib代理
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
相關(guān)文章
java實(shí)現(xiàn)隨機(jī)數(shù)生成器
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)隨機(jī)數(shù)生成器,隨機(jī)數(shù)生成小程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12MyBatis動(dòng)態(tài)SQL實(shí)現(xiàn)配置過程解析
這篇文章主要介紹了MyBatis動(dòng)態(tài)SQL實(shí)現(xiàn)配置過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03JavaWeb開發(fā)基于ssm的校園服務(wù)系統(tǒng)(實(shí)例詳解)
這篇文章主要介紹了JavaWeb開發(fā)基于ssm的校園服務(wù)系統(tǒng),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02java swagger ui 添加header請(qǐng)求頭參數(shù)的方法
今天小編就為大家分享一篇java swagger ui 添加header請(qǐng)求頭參數(shù)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-08-08Netty框架實(shí)現(xiàn)TCP/IP通信的完美過程
這篇文章主要介紹了Netty框架實(shí)現(xiàn)TCP/IP通信,這里使用的是Springboot+Netty框架,使用maven搭建項(xiàng)目,需要的朋友可以參考下2021-07-07spring boot與redis 實(shí)現(xiàn)session共享教程
這篇文章主要介紹了spring boot與redis 實(shí)現(xiàn)session共享教程,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-04-04解決Process.getInputStream()阻塞的問題
這篇文章主要介紹了解決Process.getInputStream()阻塞的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06SpringBoot 枚舉類型的自動(dòng)轉(zhuǎn)換的實(shí)現(xiàn)
一般我們在數(shù)據(jù)庫都會(huì)定義數(shù)值型的枚舉常量,不管是序列化還是反序列化都是需要我們手動(dòng)去轉(zhuǎn)換成枚舉類型的,本文主要介紹了Spring Boot 枚舉類型的自動(dòng)轉(zhuǎn)換,感興趣的可以了解一下2022-03-03