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)控實現(xià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)代理只能對實現(xiàn)了接口的類生成代理,而不能針對類
- CGLib是針對類實現(xiàn)代理,主要是對指定的類生成一個子類,覆蓋其中的方法(繼承)
2)、Spring在選擇用JDK還是CGLib的依據(jù)
- 當Bean實現(xiàn)接口時,Spring就會用JDK的動態(tài)代理
- 當Bean沒有實現(xiàn)接口時,Spring使用CGLib來實現(xiàn)
- 可以強制使用CGLib(在Spring配置中加入<aop:aspectj-autoproxy proxy-target-class=“true”/>)
3)、JDK和CGLib的性能對比
- 使用CGLib實現(xiàn)動態(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)化之后,在調用次數(shù)較少的情況下,JDK代理效率高于CGLib代理效率,只有當進行大量調用的時候,JDK1.6和JDK1.7比CGLib代理效率低一點,但是到JDK1.8的時候,JDK代理效率高于CGLib代理
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。如果你想了解更多相關內容請查看下面相關鏈接
相關文章
使用log4j2自定義配置文件位置和文件名(附log4j2.xml配置實例)
這篇文章主要介紹了使用log4j2自定義配置文件位置和文件名(附log4j2.xml配置實例),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
springboot配置文件中使用${}注入值的兩種方式小結
這篇文章主要介紹了springboot配置文件中使用${}注入值的兩種方式小結,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
SpringBoot?SpringSecurity?JWT實現(xiàn)系統(tǒng)安全策略詳解
Spring?Security是Spring的一個核心項目,它是一個功能強大且高度可定制的認證和訪問控制框架。它提供了認證和授權功能以及抵御常見的攻擊,它已經成為保護基于spring的應用程序的事實標準2022-11-11
springboot cloud使用eureka整合分布式事務組件Seata 的方法
這篇文章主要介紹了springboot cloud使用eureka整合分布式事務組件Seata 的方法 ,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-05-05

