动态代理 & 拦截器实现

iufo applet cache使用动态代理方式实现。

public class AppletCacheProxyHandler implements MethodInterceptor {

private String cacheKey = null;

AppletCacheProxyHandler(String cacheKey){
this.cacheKey = cacheKey;
}

public Object intercept(Object obj, Method method, Object[] aobj,
MethodProxy methodproxy) throws Throwable {
CacheInvokeParameter p = new CacheInvokeParameter(cacheKey,
method.getName(), method
.getParameterTypes(), aobj);
Object result = AppletCacheInvoke.invoke(p);
return result;
}

}

private static Object getCacheProxy(Class clazz, String cacheKey){
try {
AppletCacheProxyHandler interceptor = new AppletCacheProxyHandler(cacheKey);
Enhancer e = new Enhancer();
e.setSuperclass(clazz);// 指定父类
e.setCallback(interceptor);// 设置拦截器
// 针对目标对象的构造方法
Object bean = e.create(new Class[]{ICacheProxy.class, IRefreshable.class, boolean.class,boolean.class},
new Object[]{null, null, false, false});
return bean;
} catch (Throwable e){
throw new Error(e.getMessage());
}
}


1. 问题的提出             单元测试过程对于软件系统质量的提高有着非常的重要的作用,如果能对流程分支做到有效的覆盖再结合每日构建的自动测试,将对故障的迅速收敛有着很大的帮助。但是实际应用中,发现单元测试对象很多情况下对环境的依赖非常大。很多时候没有办法测试,因此单元测试在实际过程中起到的作用非常有限,仅仅对一些比较独立的算法逻辑可以测试。这成为困扰单元测试人员的主要问题。
比如一些被测试方法的入参是和环境密切相关的,如数据库连接Connection,结果集ResultSet等以及一些界面元素这些都很难模拟,单元测试时,这些参数的构造是非常困难。     
2。 解决思路 * 动态代理通过运行期拦截对被代理对象方法的调用可以很好的用于应对这类单元测试中对环境依赖性很强的类。其中可以直接使用JMock测试包来Mock这类对象并通过定义一些约束条件和返回值达到数据模拟和测试目的。如果不能使用JMock也可以直接使用CGLIB结合Objenesis来构造一些Mock对象,通过实现拦截器完成模拟对象。在系统管理模块中作者通过二者结合,很好的完成了代码可测试性改造和测试代码的构建。
从JDK1.3开始,java支持动态代理。动态代理可以实列化一个inteface,并在运行期拦截某些方法的调用。不过JDK提供的动态代理机制只能够处理interface接口,对于抽象类和一般类无能为力。


开源动态代理实现 cglib, 字节码级别实现动态代理, Spring等借以实现拦截器。



Tagged . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *