- Spring Boot進階:原理、實戰(zhàn)與面試題分析
- 鄭天民
- 716字
- 2022-07-05 09:41:49
3.3.1 測試案例設(shè)計
為了量化不同動態(tài)代理機制對性能的影響程度,我們將設(shè)計一個案例,在該案例中同樣使用3.1.2節(jié)中介紹的AccountService接口以及它的實現(xiàn)類AccountServiceImpl。我們將通過創(chuàng)建一定數(shù)量的AccountServiceImpl實例并調(diào)用它的doAccountTransaction()方法,觸發(fā)動態(tài)代理機制。
為了能夠基于不同的代理機制來創(chuàng)建代理對象,需要引入Spring中一個非常有用的注解,即@Scope注解。我們已經(jīng)在第2章中了解到該注解可以用來設(shè)置Bean的作用域。其實,@Scope注解還可以用來指定代理模式ScopedProxyMode。在Spring中,Scoped-ProxyMode是一個枚舉,如代碼清單3-15所示。
代碼清單3-15 ScopedProxyMode枚舉類代碼
public enum ScopedProxyMode { DEFAULT, NO, INTERFACES, TARGET_CLASS; }
請注意,ScopedProxyMode中的INTERFACES代表的就是JDK動態(tài)代理,而TARGET_CLASS使用的則是CGLIB動態(tài)代理。
現(xiàn)在,讓我們創(chuàng)建兩個配置類JDKProxyConfig和CGLIBProxyConfig,分別針對AccountServiceImpl指定兩種不同的代理機制。其中,JDKProxyConfig如代碼清單3-16所示。
代碼清單3-16 JDKProxyConfig類代碼
@Configuration @EnableAspectJAutoProxy public class JDKProxyConfig { @Bean @Scope(proxyMode=ScopedProxyMode.INTERFACES) public AccountService accountService(){ return new AccountServiceImpl(); } }
而CGLIBProxyConfig則如代碼清單3-17所示。
代碼清單3-17 CGLIBProxyConfig類代碼
@Configuration @EnableAspectJAutoProxy public class CGLIBProxyAppConfig { @Bean @Scope(proxyMode=ScopedProxyMode.TARGET_CLASS) public AccountService accountService(){ return new AccountServiceImpl(); } }
借助于這兩個配置文件,我們就可以通過AnnotationConfigApplicationContext這個基于注解配置的應(yīng)用上下文對象來獲取添加了不同代理機制的AccountServiceImpl對象,實現(xiàn)方式如代碼清單3-18所示。
代碼清單3-18 基于動態(tài)代理獲取AccountService實現(xiàn)類代碼
//基于JDKProxyConfig獲取AccountServiceImpl對象 AccountService accountService = new AnnotationConfigApplicationContext(JDKProxyConfig.class).getBean(AccountService.class); //基于CGLIBProxyConfig獲取AccountServiceImpl對象 AccountService accountService = new AnnotationConfigApplicationContext(CGLIBProxyConfig.class).getBean(AccountService.class);
現(xiàn)在,準(zhǔn)備工作已經(jīng)完成,讓我們編寫一個測試用例來對不同代理機制的性能進行量化。測試用例如代碼清單3-19所示。
代碼清單3-19 動態(tài)代理性能測試用例代碼
@Test public void testAopProxyPerformance() { int countofObjects = 5000; AccountServiceImpl[] unproxiedClasses = new AccountServiceImpl[countofObjects]; for (int i = 0; i < countofObjects; i++) { unproxiedClasses[i] = new AccountServiceImpl(); } AccountService[] cglibProxyClasses = new AccountService[countofObjects]; AccountService accountService = null; for (int i = 0; i < countofObjects; i++) { accountService = new AnnotationConfigApplicationContext(CGLIBProxyAppConfig.class).getBean(AccountService.class); cglibProxyClasses[i] = accountService; } AccountService[] jdkProxyClasses = new AccountService[countofObjects]; for (int i = 0; i < countofObjects; i++) { accountService = new AnnotationConfigApplicationContext(JDKProxyAppConfig.class).getBean(AccountService.class); jdkProxyClasses[i] = accountService; } long timeTookForUnproxiedObjects = invokeTargetObjects(countofObjects, unproxiedClasses); displayResults("NOProxy", timeTookForUnproxiedObjects); long timeTookForJdkProxiedObjects = invokeTargetObjects(countofObjects, jdkProxyClasses); displayResults("JDKProxy", timeTookForJdkProxiedObjects); long timeTookForCglibProxiedObjects = invokeTargetObjects(countofObjects, cglibProxyClasses); displayResults("CGLIBProxy", timeTookForCglibProxiedObjects); }
可以看到,我們分別針對不使用代理、使用JDK代理以及使用CGLIB代理的場景,創(chuàng)建了5000個AccountServiceImpl對象實例,并記錄它們的創(chuàng)建時間。完整的代碼可以參考:https://github.com/tianminzheng/spring-boot-examples/tree/main/SpringAopProxyExample。
- Java程序設(shè)計實戰(zhàn)教程
- Cocos2D-X權(quán)威指南(第2版)
- 微服務(wù)與事件驅(qū)動架構(gòu)
- 用Flutter極速構(gòu)建原生應(yīng)用
- Mastering Predictive Analytics with Python
- PhoneGap Mobile Application Development Cookbook
- Elasticsearch for Hadoop
- Android玩家必備
- ScratchJr趣味編程動手玩:讓孩子用編程講故事
- Practical Microservices
- IBM RUP參考與認(rèn)證指南
- Scala編程(第4版)
- 流暢的Python
- Instant JRebel
- Rust Quick Start Guide