JDK動態(tài)代理與CGLib動態(tài)代理的區(qū)別對比
案例:
public interface ForumService {
void removeTopic(int topicId);
void removeForum(int forumId);
}
對相關方法進行性能監(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)控實現類:
public class PerformanceMonitor {
// 通過一個ThreadLocal保存與調用線程相關的性能監(jiān)視信息
private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>();
// 啟動對某一目標方法的性能監(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)視的結果信息
mp.printPerformance();
}
}
用于記錄性能監(jiān)控信息:
public class PerformanceMonitor {
// 通過一個ThreadLocal保存與調用線程相關的性能監(jiān)視信息
private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>();
// 啟動對某一目標方法的性能監(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)視的結果信息
mp.printPerformance();
}
}
1、JDK動態(tài)代理
public class PerformanceMonitor {
// 通過一個ThreadLocal保存與調用線程相關的性能監(jiān)視信息
private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>();
// 啟動對某一目標方法的性能監(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)視的結果信息
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花費21毫秒
begin monitor...
模擬刪除Topic記錄:1012
end monitor...
com.hand.proxy.ForumServiceImpl.removeTopic花費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)代理只能對實現了接口的類生成代理,而不能針對類
- CGLib是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法(繼承)
2)、Spring在選擇用JDK還是CGLib的依據
- 當Bean實現接口時,Spring就會用JDK的動態(tài)代理
- 當Bean沒有實現接口時,Spring使用CGLib來實現
- 可以強制使用CGLib(在Spring配置中加入<aop:aspectj-autoproxy proxy-target-class=“true”/>)
3)、JDK和CGLib的性能對比
- 使用CGLib實現動態(tài)代理,CGLib底層采用ASM字節(jié)碼生成框架,使用字節(jié)碼技術生成代理類,在JDK1.6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能對聲明為final的方法進行代理,因為CGLib原理是動態(tài)生成被代理類的子類。
- 在JDK1.6、JDK1.7、JDK1.8逐步對JDK動態(tài)代理優(yōu)化之后,在調用次數較少的情況下,JDK代理效率高于CGLib代理效率,只有當進行大量調用的時候,JDK1.6和JDK1.7比CGLib代理效率低一點,但是到JDK1.8的時候,JDK代理效率高于CGLib代理
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。如果你想了解更多相關內容請查看下面相關鏈接
相關文章
JavaWeb開發(fā)基于ssm的校園服務系統(tǒng)(實例詳解)
這篇文章主要介紹了JavaWeb開發(fā)基于ssm的校園服務系統(tǒng),本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2020-02-02
java swagger ui 添加header請求頭參數的方法
今天小編就為大家分享一篇java swagger ui 添加header請求頭參數的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-08-08
spring boot與redis 實現session共享教程
這篇文章主要介紹了spring boot與redis 實現session共享教程,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-04-04
解決Process.getInputStream()阻塞的問題
這篇文章主要介紹了解決Process.getInputStream()阻塞的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06

