在写cglib动态代理实现aop的代码的时候,发现运行测试程序报出了stackoverflow异常,话不多说直接上代码:
CGLibProxy实现如下:
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* CGLibProxy动态代理类的实例
* 被代理类是否实现接口对cglib实现没有影响
*
*/
public class CGLibProxy implements MethodInterceptor {
/* @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
return null;
}*/
//根据目标对象生成一个子类作为他的代理类
public Object createProxyObject(Object obj) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(obj.getClass());//设置父类为被代理类
enhancer.setCallback(this);
Object proxyObj = enhancer.create();
//create 方法里用这个Superclass生成了子类
return proxyObj;// 返回代理对象
// 返回代理对象,返回的对象其实就是一个封装了“实现类”的代理类,是实现类的实例。
}
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
Object obj = null;
if ("addUser".equals(method.getName())) {// 过滤方法
checkPopedom();// 检查权限
}
obj = methodProxy.invoke(proxy, args);
return obj;
}
private void checkPopedom() {
System.out.println(".:检查权限 checkPopedom()!");
}
}
测试类如下:
public class Test {
public static void main(String[] args) {
Test t = new Test();
t.test();
}
private void test() {
UserManager userManager = (UserManager) new CGLibProxy()
.createProxyObject(new UserManagerImpl());
System.out.println("-----------CGLibProxy-------------");
userManager.addUser("tom", "root");
}
}
异常信息如下:
在反复打印检查权限之后,报出了stackoverflow异常。
问题到底出在哪儿呢?
仔细查看以及debug自己的代码之后,发现问题出在下面这一行:
obj = methodProxy.invoke(proxy, args);
通过反射去掉用传入对象的增强方法,而这里传入的对象是proxy类,而proxy类自己又回调用这个增强方法,因此无限的调用增强方法,导致了stackoverflow的出现。
修改方式:
在实现动态代理的时候,在增强方法里实现了增强逻辑之后,需要调用的是被代理类本身需要执行的方法,因此这里应该传入的不是proxy对象,而是在createPrxoxy方法中指定需要代理的类的对象。修改代码如下:
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* CGLibProxy动态代理类的实例
* 被代理类是否实现接口对cglib实现没有影响
*
*/
public class CGLibProxy implements MethodInterceptor {
/* @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)
throws Throwable {
return null;
}*/
//根据目标对象生成一个子类作为他的代理类
private Object target;
public Object createProxyObject(Object obj) {
Enhancer enhancer = new Enhancer();
target = obj;
enhancer.setSuperclass(obj.getClass());//设置父类为被代理类
enhancer.setCallback(this);
Object proxyObj = enhancer.create();
//create 方法里用这个Superclass生成了子类
return proxyObj;// 返回代理对象
// 返回代理对象,返回的对象其实就是一个封装了“实现类”的代理类,是实现类的实例。
}
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
Object obj = null;
if ("addUser".equals(method.getName())) {// 过滤方法
checkPopedom();// 检查权限
}
obj = methodProxy.invoke(target, args);
return obj;
}
private void checkPopedom() {
System.out.println(".:检查权限 checkPopedom()!");
}
}
再运行测试类就成功了。