JDK動態(tài)代理與CGLib動態(tài)代理的區(qū)別對比
案例:
public interface ForumService {
void removeTopic(int topicId);
void removeForum(int forumId);
}
對相關(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 {
// 通過一個ThreadLocal保存與調(diào)用線程相關(guān)的性能監(jiān)視信息
private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>();
// 啟動對某一目標(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 {
// 通過一個ThreadLocal保存與調(diào)用線程相關(guān)的性能監(jiān)視信息
private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>();
// 啟動對某一目標(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動態(tài)代理
public class PerformanceMonitor {
// 通過一個ThreadLocal保存與調(diào)用線程相關(guān)的性能監(jiān)視信息
private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>();
// 啟動對某一目標(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動態(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動態(tài)代理只能對實(shí)現(xiàn)了接口的類生成代理,而不能針對類
- CGLib是針對類實(shí)現(xiàn)代理,主要是對指定的類生成一個子類,覆蓋其中的方法(繼承)
2)、Spring在選擇用JDK還是CGLib的依據(jù)
- 當(dāng)Bean實(shí)現(xiàn)接口時,Spring就會用JDK的動態(tài)代理
- 當(dāng)Bean沒有實(shí)現(xiàn)接口時,Spring使用CGLib來實(shí)現(xiàn)
- 可以強(qiáng)制使用CGLib(在Spring配置中加入<aop:aspectj-autoproxy proxy-target-class=“true”/>)
3)、JDK和CGLib的性能對比
- 使用CGLib實(shí)現(xiàn)動態(tài)代理,CGLib底層采用ASM字節(jié)碼生成框架,使用字節(jié)碼技術(shù)生成代理類,在JDK1.6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能對聲明為final的方法進(jìn)行代理,因為CGLib原理是動態(tài)生成被代理類的子類。
- 在JDK1.6、JDK1.7、JDK1.8逐步對JDK動態(tài)代理優(yōu)化之后,在調(diào)用次數(shù)較少的情況下,JDK代理效率高于CGLib代理效率,只有當(dāng)進(jìn)行大量調(diào)用的時候,JDK1.6和JDK1.7比CGLib代理效率低一點(diǎn),但是到JDK1.8的時候,JDK代理效率高于CGLib代理
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接
相關(guān)文章
java實(shí)現(xiàn)隨機(jī)數(shù)生成器
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)隨機(jī)數(shù)生成器,隨機(jī)數(shù)生成小程序,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12
MyBatis動態(tài)SQL實(shí)現(xiàn)配置過程解析
這篇文章主要介紹了MyBatis動態(tài)SQL實(shí)現(xiàn)配置過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-03-03
JavaWeb開發(fā)基于ssm的校園服務(wù)系統(tǒng)(實(shí)例詳解)
這篇文章主要介紹了JavaWeb開發(fā)基于ssm的校園服務(wù)系統(tǒng),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2020-02-02
java swagger ui 添加header請求頭參數(shù)的方法
今天小編就為大家分享一篇java swagger ui 添加header請求頭參數(shù)的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-08-08
Netty框架實(shí)現(xiàn)TCP/IP通信的完美過程
這篇文章主要介紹了Netty框架實(shí)現(xiàn)TCP/IP通信,這里使用的是Springboot+Netty框架,使用maven搭建項目,需要的朋友可以參考下2021-07-07
spring boot與redis 實(shí)現(xiàn)session共享教程
這篇文章主要介紹了spring boot與redis 實(shí)現(xiàn)session共享教程,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-04-04
解決Process.getInputStream()阻塞的問題
這篇文章主要介紹了解決Process.getInputStream()阻塞的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06
SpringBoot 枚舉類型的自動轉(zhuǎn)換的實(shí)現(xiàn)
一般我們在數(shù)據(jù)庫都會定義數(shù)值型的枚舉常量,不管是序列化還是反序列化都是需要我們手動去轉(zhuǎn)換成枚舉類型的,本文主要介紹了Spring Boot 枚舉類型的自動轉(zhuǎn)換,感興趣的可以了解一下2022-03-03

