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é)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
相關(guān)文章
深入理解 Java 中的 Switch 語(yǔ)句示例詳解
在Java編程中,switch語(yǔ)句通過表達(dá)式值來執(zhí)行不同代碼塊,本文介紹switch語(yǔ)法、案例、注意事項(xiàng),以及與if語(yǔ)句的對(duì)比,包括基本語(yǔ)法、關(guān)鍵字、表達(dá)式、case常量、break和default的使用,以及如何根據(jù)輸入的字符輸出星期、大小寫轉(zhuǎn)換、成績(jī)判斷和季節(jié)判斷等實(shí)際應(yīng)用場(chǎng)景2024-10-10
使用log4j2自定義配置文件位置和文件名(附log4j2.xml配置實(shí)例)
這篇文章主要介紹了使用log4j2自定義配置文件位置和文件名(附log4j2.xml配置實(shí)例),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
Java基礎(chǔ)知識(shí)精通各種運(yùn)算符
計(jì)算機(jī)的最基本用途之一就是執(zhí)行數(shù)學(xué)運(yùn)算,作為一門計(jì)算機(jī)語(yǔ)言,Java也提供了一套豐富的運(yùn)算符來操縱變量,本篇對(duì)大家的學(xué)習(xí)或工作具有一定的價(jià)值,需要的朋友可以參考下2022-04-04
Java 是如何讀取和寫入瀏覽器Cookies的實(shí)例詳解
這篇文章主要介紹了Java 是如何讀取和寫入瀏覽器Cookies的實(shí)例的相關(guān)資料,需要的朋友可以參考下2016-09-09
springboot配置文件中使用${}注入值的兩種方式小結(jié)
這篇文章主要介紹了springboot配置文件中使用${}注入值的兩種方式小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
SpringBoot?SpringSecurity?JWT實(shí)現(xiàn)系統(tǒng)安全策略詳解
Spring?Security是Spring的一個(gè)核心項(xiàng)目,它是一個(gè)功能強(qiáng)大且高度可定制的認(rèn)證和訪問控制框架。它提供了認(rèn)證和授權(quán)功能以及抵御常見的攻擊,它已經(jīng)成為保護(hù)基于spring的應(yīng)用程序的事實(shí)標(biāo)準(zhǔn)2022-11-11
springboot cloud使用eureka整合分布式事務(wù)組件Seata 的方法
這篇文章主要介紹了springboot cloud使用eureka整合分布式事務(wù)組件Seata 的方法 ,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-05-05

