代码改变世界

反射调用异常InvocationTargetException和代理类抛出异常

2017-11-15 01:29  Loull  阅读(1722)  评论(0)    收藏  举报
反射调用方法,如果方法抛出异常,会被包装成InvocationTargetException。
如果反射对象被代理了,在代理类中抛出异常,不会被包装成InvocationTargetException。
 
package com.loull.test.aop;

public interface Person {
    void sayHello();
}

 

package com.loull.test.aop;

public class PersonImpl implements Person {

    @Override
    public void sayHello() {
        throw new RuntimeException("sayHello Exp");
    }

}

 

package com.loull.test.aop;

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;

public class ProxyExpTest {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException,
                                           SecurityException, InstantiationException,
                                           IllegalAccessException {
        Class<?> personImplClz = Class.forName("com.loull.test.aop.PersonImpl");
        Method method = personImplClz.getMethod("sayHello");

        try {
            method.invoke(personImplClz.newInstance());
        } catch (Exception e) {
            e.printStackTrace();
        }

        Object person = personImplClz.newInstance();
        Person proxyPersion = (Person) Proxy.newProxyInstance(personImplClz.getClassLoader(),
            person.getClass().getInterfaces(), new MyInvocationHandler(person, true));
        try {
            proxyPersion.sayHello();
        } catch (Throwable e) {
            e.printStackTrace();
        }

        System.out.println("cglib");
        MyCglibProxy cglibProxy = new MyCglibProxy();
        Person cglibPerson = (Person) cglibProxy.getInstance(personImplClz.newInstance(), true);
        try {
            cglibPerson.sayHello();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("cglib end");
    }

    static class MyCglibProxy implements MethodInterceptor {

        private Object  target;

        private boolean exp;

        public Object getInstance(Object target, boolean exp) {
            this.target = target;
            this.exp = exp;

            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(this.target.getClass());
            //
            enhancer.setCallback(this);
            //
            return enhancer.create();
        }

        @Override
        public Object intercept(Object obj, Method method, Object[] args,
                                MethodProxy proxy) throws Throwable {
            System.out.println("cglib_before invoke");
            if (exp) {
                throw new OutOfMemoryError("proxy exp cglib");
            }
            Object result = proxy.invokeSuper(obj, args);
            System.out.println("cglib_after invoke");
            return result;
        }

    }

    static class MyInvocationHandler implements InvocationHandler {

        private Object  target;

        private boolean exp;

        public MyInvocationHandler(Object target, boolean exp) {
            this.target = target;
            this.exp = exp;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("before invoke");
            if (exp) {
                throw new OutOfMemoryError("proxy exp");
            }
            Object result = method.invoke(target, args);
            System.out.println("after invoke");
            return result;
        }

    }

}

 

输出:

java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.alipay.test.aop.ProxyExpTest.main(ProxyExpTest.java:20)
Caused by: java.lang.RuntimeException: sayHello Exp
	at com.alipay.test.aop.PersonImpl.sayHello(PersonImpl.java:7)
	... 5 more
java.lang.OutOfMemoryError: proxy exp
	at com.alipay.test.aop.ProxyExpTest$MyInvocationHandler.invoke(ProxyExpTest.java:92)
	at com.sun.proxy.$Proxy0.sayHello(Unknown Source)
	at com.alipay.test.aop.ProxyExpTest.main(ProxyExpTest.java:29)
before invoke
cglib
cglib_before invoke
java.lang.OutOfMemoryError: proxy exp cglib
	at com.alipay.test.aop.ProxyExpTest$MyCglibProxy.intercept(ProxyExpTest.java:68)
	at com.alipay.test.aop.PersonImpl$$EnhancerByCGLIB$$9174c686.sayHello(<generated>)
	at com.alipay.test.aop.ProxyExpTest.main(ProxyExpTest.java:38)
cglib end