官术网_书友最值得收藏!

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

主站蜘蛛池模板: 常熟市| 太白县| 岳西县| 和田市| 右玉县| 孙吴县| 双流县| 凤冈县| 嘉义市| 南昌市| 玉屏| 隆安县| 澎湖县| 德昌县| 临颍县| 佛学| 贡山| 陇川县| 临沭县| 五常市| 台南县| 三门县| 台南县| 于都县| 平远县| 波密县| 惠水县| 蓬安县| 鸡东县| 淮北市| 昌黎县| 莱芜市| 广元市| 华亭县| 崇州市| 通榆县| 历史| 施甸县| 来安县| 巴彦淖尔市| 温宿县|