本篇文章為大家展示了JDK動態代理與CGLib動態代理有什么不同,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
案例:
public interface ForumService { void removeTopic(int topicId); void removeForum(int forumId); }
對相關方法進行性能監控
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(); } }
性能監控實現類:
public class PerformanceMonitor { // 通過一個ThreadLocal保存與調用線程相關的性能監視信息 private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>(); // 啟動對某一目標方法的性能監視 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(); // 打印出方法性能監視的結果信息 mp.printPerformance(); } }
用于記錄性能監控信息:
public class PerformanceMonitor { // 通過一個ThreadLocal保存與調用線程相關的性能監視信息 private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>(); // 啟動對某一目標方法的性能監視 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(); // 打印出方法性能監視的結果信息 mp.printPerformance(); } }
1、JDK動態代理
public class PerformanceMonitor { // 通過一個ThreadLocal保存與調用線程相關的性能監視信息 private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>(); // 啟動對某一目標方法的性能監視 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(); // 打印出方法性能監視的結果信息 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動態代理
<!-- 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的區別
JDK動態代理只能對實現了接口的類生成代理,而不能針對類
CGLib是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法(繼承)
2)、Spring在選擇用JDK還是CGLib的依據
當Bean實現接口時,Spring就會用JDK的動態代理
當Bean沒有實現接口時,Spring使用CGLib來實現
可以強制使用CGLib(在Spring配置中加入<aop:aspectj-autoproxy proxy-target-class=“true”/>)
3)、JDK和CGLib的性能對比
使用CGLib實現動態代理,CGLib底層采用ASM字節碼生成框架,使用字節碼技術生成代理類,在JDK1.6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能對聲明為final的方法進行代理,因為CGLib原理是動態生成被代理類的子類。
在JDK1.6、JDK1.7、JDK1.8逐步對JDK動態代理優化之后,在調用次數較少的情況下,JDK代理效率高于CGLib代理效率,只有當進行大量調用的時候,JDK1.6和JDK1.7比CGLib代理效率低一點,但是到JDK1.8的時候,JDK代理效率高于CGLib代理
上述內容就是JDK動態代理與CGLib動態代理有什么不同,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。