paypal可做网站,wordpress伪静态win,wordpress+技术类模板,免费企业黄页下载1 概述 在讨论动态代理机制时#xff0c;一个不可避免的话题是性能。无论采用JDK动态代理还是CGLIB动态代理#xff0c;本质上都是在原有目标对象上进行了封装和转换#xff0c;这个过程需要消耗资源和性能。而JDK和CGLIB动态代理的内部实现过程本身也存在很大差异。下面将讨…1 概述 在讨论动态代理机制时一个不可避免的话题是性能。无论采用JDK动态代理还是CGLIB动态代理本质上都是在原有目标对象上进行了封装和转换这个过程需要消耗资源和性能。而JDK和CGLIB动态代理的内部实现过程本身也存在很大差异。下面将讨论两种动态代理机制对系统运行性能所带来的影响。
2 测试案例设计 为了量化不同动态代理对性能的影响程度将设计一个案例在该案例中同样使用前面介绍的AccountService接口以及它的实现类AccountServiceImpl。将通过创建一定数量的AccountServiceImpl实例并调用它的doAccountTransaction()方法触发动态代理机制。 为了能够基于不同的代理机制来创建对象需要引入Spring中一个非常有用的注解即Scope。这个注解可以用来设置Bean的作用域还可以用来指定代理模式ScopedProxyMode在Spring中ScopedProxyMode是一个枚举代码如下
public enum ScopedProxyMode {DEFAULT,NO,INTERFACES,TARGET_CLASS;private ScopedProxyMode() {}
}这里的INTERFACES代表的就是JDK动态代理而TARGET_CLASS使用的则是CGLIB动态代理。现在创建两个配置类JDKProxyConfig和CGLIBProxyConfig分别针对AccountServiceImpl指定两种不同的代理机制。JDKProxyConfig代码如下
Configuration
EnableAspectJAutoProxy
public class JDKProxyConfig {BeanScope(proxyMode ScopedProxyMode.INTERFACES)public AccountService accountService(){return new AccountServiceImpl();}
}CGLIBProxyConfig代码如下
EnableAspectJAutoProxy
Configuration
public class CGLIBProxyConfig {BeanScope(proxyMode ScopedProxyMode.TARGET_CLASS)public AccountService accountService(){return new AccountServiceImpl();}
} 借助于这两个配置类就可以通过AnnotationConfigApplicationContext这个基于注解配置的应用上下文对象来获取添加了不同代理机制的AccountServiceImpl对象。准备工作已经完成编写一个测试用例来对不同代理机制的性能进行量化。代码如下
public class ProxyTest {private static final Logger LOGGER Logger.getLogger(ProxyTest.class);Testpublic void testAopProxyPerformance() throws MinimumAccountException {int countObjects 5000;AccountServiceImpl[] unproxiedClasses new AccountServiceImpl[countObjects];for (int i 0; i countObjects; i) {unproxiedClasses[i] new AccountServiceImpl();}AccountService[] cglibProxyClasses new AccountService[countObjects];AccountService accountService null;for (int i 0; i countObjects; i) {accountService new AnnotationConfigApplicationContext(CGLIBProxyConfig.class).getBean(AccountService.class);cglibProxyClasses[i] accountService;}AccountService[] jdkProxyClasses new AccountService[countObjects];for (int i 0; i countObjects; i) {accountService new AnnotationConfigApplicationContext(JDKProxyConfig.class).getBean(AccountService.class);jdkProxyClasses[i] accountService;}long noProxy invokeTargetObjects(countObjects, unproxiedClasses);displayResults(NOProxy,noProxy);long jdkProxy invokeTargetObjects(countObjects, jdkProxyClasses);displayResults(JDKProxy,jdkProxy);long cglibProxy invokeTargetObjects(countObjects, cglibProxyClasses);displayResults(cglibProxy,cglibProxy);}private void displayResults(String label, long timeTook) {LOGGER.info(label : timeTook (ns) (timeTook / 1000000) (ms));}private long invokeTargetObjects(int countObjects,AccountService[] classes) throws MinimumAccountException {long start System.nanoTime();Account source new Account(101,Account1);Account dest new Account(102,Account2);for (int i 0; i countObjects; i) {classes[i].doAccountTransaction(source, dest, 100);}long end System.nanoTime();return end - start;}
} 运行结果 可以看到分别针对不使用代理、使用JDK代理和CGLIB代理的场景创建了5000个AccountServiceImpl对象实例并记录它们的创建时间。以上量化结果取决于不同的机器配置但不影响得出结论。从结果中不难看出JDK动态代理在性能上优于CGLIB动态代理但相差并不大。 其他类的代码如下
public class Account {private String accountName;private Integer accountNumber;public String getAccountName() {return accountName;}public void setAccountName(String accountName) {this.accountName accountName;}public Integer getAccountNumber() {return accountNumber;}public void setAccountNumber(Integer accountNumber) {this.accountNumber accountNumber;}public Account(Integer accountNumber, String accountName) {this.accountNumber accountNumber;this.accountName accountName;}
}
public interface AccountService {boolean doAccountTransaction(Account source, Account dest, int amount);
}
public class AccountServiceImpl implements AccountService {Overridepublic boolean doAccountTransaction(Account source, Account dest, int amount) {return true;}}