StackOverFlow异常记录

在写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异常记录_第1张图片

在反复打印检查权限之后,报出了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()!");
    }
}

再运行测试类就成功了。

 

 

 

 

 

 

 

 

你可能感兴趣的:(java)