Spring AOP 测试
2014-04-28 00:00
85 查看
动态代理测试
JDK 1.7
public interface CgTestInterface {
public void print();
public void print1();
// public void print2();
}
public class CgTest implements CgTestInterface {
public void print() {
System.out.println(getClass().getName() + " print: hello world");
print1();
print2();
}
public void print1() {
System.out.println(getClass().getName() + " print1: hello world");
}
private void print2() {
System.out.println(getClass().getName() + " print2: hello world");
}
}
public class PerformanceMonitor {
static long begTime;
public static void begin() {
System.out.println("begins...");
begTime = System.currentTimeMillis();
}
public static void end(String strName) {
System.out.println(strName + " : " + (System.currentTimeMillis() - begTime)+“ms”);
}
}
public class PerformanceHandler implements InvocationHandler {
private Object target;
public PerformanceHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
PerformanceMonitor.begin();
System.out.println(proxy.getClass().getName());
Object obj = method.invoke(target, args);
PerformanceMonitor.end(method.getName());
return obj;
}
}
public class TestMain {
public static void main(String[] args) {
CgTestInterface cg = new CgTest();
PerformanceHandler handler = new PerformanceHandler(cg);
CgTestInterface proxy1 = (CgTestInterface)Proxy.newProxyInstance(cg.getClass().getClassLoader(), cg.getClass().getInterfaces(), handler);
System.out.println(proxy1.getClass().getName());
proxy1.print();
}
}
测试结果:
com.sun.proxy.$Proxy0
begins...
com.sun.proxy.$Proxy0
com.cglib.CgTest print: hello world
com.cglib.CgTest print1: hello world
com.cglib.CgTest print2: hello world
print : 0ms
基于JDK的动态代理生成了一个接口实现类。当调用print时,实际调用的是该代理类的print方法,在PerformanceHandler中为该方法实现了增强,所以实际调用的序列是:
PerformanceMonitor.begin();
Object obj = method.invoke(target, args);
PerformanceMonitor.end(method.getName());
而通过method.invoke调用了CgTest的print方法。所以增强的代码不会直接作用于CgTest中的方法,故print1还是按CgTest中的代码执行。
虽然通过proxy1执行,但实际是用CgTest实例进行的调用;
通过CGLib实现AOP
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class cla) {
enhancer.setSuperclass(cla);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
// TODO Auto-generated method stub
PerformanceMonitor.begin();
Object result = arg3.invokeSuper(arg0, arg2);
System.out.println(arg0.getClass().getName());
PerformanceMonitor.end(arg1.getName());
return result;
}
}
public class TestMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
CglibProxy proxy = new CglibProxy();
CgTest test = (CgTest)proxy.getProxy(CgTest.class);
System.out.println(test.getClass().getName());
test.print();
}
}
测试结果:
com.cglib.CgTest$$EnhancerByCGLIB$$4d4122d
begins...
com.cglib.CgTest$$EnhancerByCGLIB$$4d4122d
com.cglib.CgTest$$EnhancerByCGLIB$$4d4122d print: hello world
begins...
com.cglib.CgTest$$EnhancerByCGLIB$$4d4122d
com.cglib.CgTest$$EnhancerByCGLIB$$4d4122d print1: hello world
print1 : 0ms
com.cglib.CgTest$$EnhancerByCGLIB$$4d4122d print2: hello world
print : 1ms
结果发现print及其内部调用的print1方法都被添加了增强功能代码。从CgTest派生了一个子类,重写了所有方法,所有的调用都是在子类方法之间进行。
在CgTest对print方法做如下改动:
public void print() {
System.out.println(this.getClass().getName() + " print: hello world");
try {
CgTest.class.getMethod("print1").invoke(this);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException
| SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//print1();
//print2();
}
执行的结果进一步证明了这点:
com.cglib.CgTest$$EnhancerByCGLIB$$c6c06c4
begins...
com.cglib.CgTest$$EnhancerByCGLIB$$c6c06c4
com.cglib.CgTest$$EnhancerByCGLIB$$c6c06c4 print: hello world
begins...
com.cglib.CgTest$$EnhancerByCGLIB$$c6c06c4
com.cglib.CgTest$$EnhancerByCGLIB$$c6c06c4 print1: hello world
print1 : 0ms
print : 0ms
如果将CgTest改为final,则运行时抛出异常。
当然,CGLib也可以与JDK一样,对接口进行代理,得到的结果与JDK一样。
但是在spring的aop中,虽然是基于jdk或者CGLib实现,但是经过测试,五种增强方式的调用都是发生在被代理类内部,方法调用方法不会带来多重增强,这个不知道为啥,暂留后来研究。
JDK 1.7
public interface CgTestInterface {
public void print();
public void print1();
// public void print2();
}
public class CgTest implements CgTestInterface {
public void print() {
System.out.println(getClass().getName() + " print: hello world");
print1();
print2();
}
public void print1() {
System.out.println(getClass().getName() + " print1: hello world");
}
private void print2() {
System.out.println(getClass().getName() + " print2: hello world");
}
}
public class PerformanceMonitor {
static long begTime;
public static void begin() {
System.out.println("begins...");
begTime = System.currentTimeMillis();
}
public static void end(String strName) {
System.out.println(strName + " : " + (System.currentTimeMillis() - begTime)+“ms”);
}
}
public class PerformanceHandler implements InvocationHandler {
private Object target;
public PerformanceHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
PerformanceMonitor.begin();
System.out.println(proxy.getClass().getName());
Object obj = method.invoke(target, args);
PerformanceMonitor.end(method.getName());
return obj;
}
}
public class TestMain {
public static void main(String[] args) {
CgTestInterface cg = new CgTest();
PerformanceHandler handler = new PerformanceHandler(cg);
CgTestInterface proxy1 = (CgTestInterface)Proxy.newProxyInstance(cg.getClass().getClassLoader(), cg.getClass().getInterfaces(), handler);
System.out.println(proxy1.getClass().getName());
proxy1.print();
}
}
测试结果:
com.sun.proxy.$Proxy0
begins...
com.sun.proxy.$Proxy0
com.cglib.CgTest print: hello world
com.cglib.CgTest print1: hello world
com.cglib.CgTest print2: hello world
print : 0ms
基于JDK的动态代理生成了一个接口实现类。当调用print时,实际调用的是该代理类的print方法,在PerformanceHandler中为该方法实现了增强,所以实际调用的序列是:
PerformanceMonitor.begin();
Object obj = method.invoke(target, args);
PerformanceMonitor.end(method.getName());
而通过method.invoke调用了CgTest的print方法。所以增强的代码不会直接作用于CgTest中的方法,故print1还是按CgTest中的代码执行。
虽然通过proxy1执行,但实际是用CgTest实例进行的调用;
通过CGLib实现AOP
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class cla) {
enhancer.setSuperclass(cla);
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
// TODO Auto-generated method stub
PerformanceMonitor.begin();
Object result = arg3.invokeSuper(arg0, arg2);
System.out.println(arg0.getClass().getName());
PerformanceMonitor.end(arg1.getName());
return result;
}
}
public class TestMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
CglibProxy proxy = new CglibProxy();
CgTest test = (CgTest)proxy.getProxy(CgTest.class);
System.out.println(test.getClass().getName());
test.print();
}
}
测试结果:
com.cglib.CgTest$$EnhancerByCGLIB$$4d4122d
begins...
com.cglib.CgTest$$EnhancerByCGLIB$$4d4122d
com.cglib.CgTest$$EnhancerByCGLIB$$4d4122d print: hello world
begins...
com.cglib.CgTest$$EnhancerByCGLIB$$4d4122d
com.cglib.CgTest$$EnhancerByCGLIB$$4d4122d print1: hello world
print1 : 0ms
com.cglib.CgTest$$EnhancerByCGLIB$$4d4122d print2: hello world
print : 1ms
结果发现print及其内部调用的print1方法都被添加了增强功能代码。从CgTest派生了一个子类,重写了所有方法,所有的调用都是在子类方法之间进行。
在CgTest对print方法做如下改动:
public void print() {
System.out.println(this.getClass().getName() + " print: hello world");
try {
CgTest.class.getMethod("print1").invoke(this);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException
| SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//print1();
//print2();
}
执行的结果进一步证明了这点:
com.cglib.CgTest$$EnhancerByCGLIB$$c6c06c4
begins...
com.cglib.CgTest$$EnhancerByCGLIB$$c6c06c4
com.cglib.CgTest$$EnhancerByCGLIB$$c6c06c4 print: hello world
begins...
com.cglib.CgTest$$EnhancerByCGLIB$$c6c06c4
com.cglib.CgTest$$EnhancerByCGLIB$$c6c06c4 print1: hello world
print1 : 0ms
print : 0ms
如果将CgTest改为final,则运行时抛出异常。
当然,CGLib也可以与JDK一样,对接口进行代理,得到的结果与JDK一样。
但是在spring的aop中,虽然是基于jdk或者CGLib实现,但是经过测试,五种增强方式的调用都是发生在被代理类内部,方法调用方法不会带来多重增强,这个不知道为啥,暂留后来研究。
相关文章推荐
- Spring基于注解的AOP测试
- java代理课程测试 spring AOP代理简单测试
- CGLIB实现AOP代理的测试类,与Spring分离,加深对面向切面编程的理解
- 使用AOP,在spring中实现简单的性能测试
- 回顾SpringAOP,简单的测试,加深理解
- spring AOP 配置事务不起作用的问题(用Junit测试service)
- 【SSH】Spring学习(二)使用注解配置Spring、安装STS插件、Spring与junit整合测试、AOP
- 基于注解的测试Spring-aop通知顺序
- 基于注解的Spring AOP实现demo(测试通知顺序)
- spring aop 切面测试
- Spring AOP小测试(ProxyFactoryBean)
- spring AOP 的几种实现方式(能测试)
- [程序代写推荐]java代理课程测试 spring AOP代理简单测试
- Spring入门(二)— IOC注解、Spring测试、AOP入门
- JAVAEE——spring02:使用注解配置spring、sts插件、junit整合测试和aop演示
- [找程序员代写推荐]java代理课程测试 spring AOP代理简单测试
- Spring aop测试实例
- 使用Spring进行切面(AOP)编程
- Spring和junit测试之配置文件路径
- Spring学习笔记——AOP