使用CGLib代理报java.lang.StackOverflowError问题

丶深蓝 发布于 2013/11/05 13:31
阅读 1K+
收藏 0

解读下一代网络:算力网络正从理想照进现实!>>>

package sun.testProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import org.junit.Test;

public class TestProxy {
	@Test
	public void testProxy() {
		Hello helloProxy = new HelloProxy();
		helloProxy.say("Sun");
	}

	@Test	//动态代理:要代理的类必须要有实现接口
	public void testDynamicProxy(){
		Hello hello = new HelloImpl();
		
		DynamicProxy dynamicProxy = new DynamicProxy(hello);
		Hello helloProxy = (Hello) Proxy.newProxyInstance(
				hello.getClass().getClassLoader(),
				hello.getClass().getInterfaces(), 
				dynamicProxy);
		helloProxy.say("Sun");
	}
	
	@Test	//测试封装Proxy获取方法后的情况
	public void testDynamicProxyPackage(){
		Hello hello = new HelloImpl();
		DynamicProxy dynamicProxy = new DynamicProxy(hello);
		Hello helloProxy = dynamicProxy.getProxy();
		helloProxy.say("Sun");
	}
	@Test	//方法级别的代理,不用实现接口
	public void testCGLibProxy(){
		CGLibProxy cgLibProxy = new CGLibProxy();
		HelloImpl helloProxy = cgLibProxy.getProxy(HelloImpl.class);
		helloProxy.say("Sun");
	}
}

/**
 * 接口
 * @author Administrator
 */
interface Hello{
	void say(String name);
}

/**
 * 实现类
 * @author Administrator
 */
class HelloImpl implements Hello{
	
	@Override
	public void say(String name) {
		System.out.println("Hello!" + name);
	}
}

//代理类(静态代理)
class HelloProxy implements Hello{

	private HelloImpl helloImpl;
	
	public HelloProxy() {
		helloImpl = new HelloImpl();
	}
	@Override
	public void say(String name) {
		before();
		helloImpl.say(name);
		after();
	}
	private void after() {
		System.out.println("After....");
	}
	private void before() {
		System.out.println("before...");
	}
}

//动态代理
class DynamicProxy implements InvocationHandler{

	private Object target;
	
	public DynamicProxy(Object target) {
		this.target = target;
	}
	@SuppressWarnings("unchecked")
	public <T> T getProxy(){
		return (T) Proxy.newProxyInstance(
				target.getClass().getClassLoader(), 
				target.getClass().getInterfaces(), 
				this);
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		before();
		Object result = method.invoke(target, args);
		method.invoke(target, args);
		after();
		return result;
	}
	private void after() {
		System.out.println("After....");
	}
	private void before() {
		System.out.println("before...");
	}
}

/**
 * CGLib代理
 * @author Administrator
 */
class CGLibProxy implements MethodInterceptor{

	@SuppressWarnings("unchecked")
	public <T> T getProxy(Class<T> cls){
		return (T) Enhancer.create(cls, this);
	}
	
	@Override
	public Object intercept(Object arg0, Method arg1, Object[] arg2,
			MethodProxy arg3) throws Throwable {
		before();
		Object result = arg3.invoke(arg0, arg2);
		after();
		return result;
	}
	private void after() {
		System.out.println("After....");
	}

	private void before() {
		System.out.println("before...");
	}
}

报错:

java.lang.StackOverflowError
	at sun.nio.cs.UTF_8$Encoder.encodeArrayLoop(UTF_8.java:446)
	at sun.nio.cs.UTF_8$Encoder.encodeLoop(UTF_8.java:517)
	at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:544)
	at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:252)
	at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:106)
	at java.io.OutputStreamWriter.write(OutputStreamWriter.java:190)
	at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:111)
	at java.io.PrintStream.write(PrintStream.java:476)
	at java.io.PrintStream.print(PrintStream.java:619)
	at java.io.PrintStream.println(PrintStream.java:756)
	at sun.testProxy.CGLibProxy.before(TestProxy.java:145)
	at sun.testProxy.CGLibProxy.intercept(TestProxy.java:135)
	at sun.testProxy.HelloImpl$$EnhancerByCGLIB$$7ac88992.say(<generated>)
	at sun.testProxy.HelloImpl$$FastClassByCGLIB$$bcd464de.invoke(<generated>)
	at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at sun.testProxy.CGLibProxy.intercept(TestProxy.java:136)
	at sun.testProxy.HelloImpl$$EnhancerByCGLIB$$7ac88992.say(<generated>)
	at sun.testProxy.HelloImpl$$FastClassByCGLIB$$bcd464de.invoke(<generated>)
	at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at sun.testProxy.CGLibProxy.intercept(TestProxy.java:136)
	at sun.testProxy.HelloImpl$$EnhancerByCGLIB$$7ac88992.say(<generated>)
	at sun.testProxy.HelloImpl$$FastClassByCGLIB$$bcd464de.invoke(<generated>)
	at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at sun.testProxy.CGLibProxy.intercept(TestProxy.java:136)

....

加载中
0
黄勇
黄勇

使用 invokeSuper 方法,而不是 invoke 方法。

...
	@Override
	public Object intercept(Object arg0, Method arg1, Object[] arg2,
			MethodProxy arg3) throws Throwable {
		before();
//		Object result = arg3.invoke(arg0, arg2);
		Object result = arg3.invokeSuper(arg0, arg2);
		after();
		return result;
	}
...
给我最佳答案吧!哈哈!
丶深蓝
丶深蓝
哎,还真是,看走眼了,多谢指点哦
0
震秦
震秦
把你的CGLibProxy类getProxy()方法更改为下面的内容试试
Enhancer enhancer = new Enhancer();
        //设置父类
        enhancer.setSuperclass(cls);
        //设置需要织入的逻辑
        enhancer.setCallback(this);
        return (T) enhancer.create();
丶深蓝
丶深蓝
试了下,问题不在这儿,我是照着@黄勇 的博客《Proxy那些事儿》敲的,方法写错了,马虎大意了
返回顶部
顶部