spring之aop方法内部调用问题

来源:互联网 发布:eclipse java 贪吃蛇 编辑:程序博客网 时间:2024/06/01 19:27

现象描述:假设有一个service,其中有A B 两个方法,A B都被aop托管,且A中调用了B方法,这时请求方法A的时候只会触发A的aop逻辑而不会触发B的aop逻辑。

public interface UserService {    void test();}   
public class UserServiceImpl implements UserService {    @Override    public void test() {        System.out.println("UserService 逻辑执行。。。。");    }}

jdk动态代理:

/***代理类真正执行的是InvocationHandler的invoke方法*/public class MyInvocationHandler implements InvocationHandler {    private Object target;    public MyInvocationHandler(Object obj) {        this.target = obj;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("Befroe invoke .............");        Object r = method.invoke(target, args);        System.out.println("After invoke ...............");        return r;    }}
UserServiceImpl impl = new UserServiceImpl();        UserService service =                (UserService) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),                        impl.getClass().getInterfaces(), new MyInvocationHandler(impl));        service.test();//这里将动态代理生成的类文件写入磁盘,方便反编译        byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy11",                UserServiceImpl.class.getInterfaces());        FileOutputStream out = null;        try {            out = new FileOutputStream("C:\\Users\\nieyanshun\\Desktop\\test\\clazz.class");            out.write(classFile);            out.flush();        } catch (Exception e) {            e.printStackTrace();        } finally {            try {                if (null != out)                    out.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }

以上是jdk动态代理的示例代码,我们反编译看下:

import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;import org.flying.bird.rpc.proxy.UserService;public final class $Proxy11  extends Proxy  implements UserService{  private static Method m1;  private static Method m3;  private static Method m2;  private static Method m0;  public $Proxy11(InvocationHandler paramInvocationHandler)  {    super(paramInvocationHandler);  }  public final boolean equals(Object paramObject)  {    try    {      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();    }    catch (Error|RuntimeException localError)    {      throw localError;    }    catch (Throwable localThrowable)    {      throw new UndeclaredThrowableException(localThrowable);    }  }  public final void test()  {    try    {      this.h.invoke(this, m3, null);      return;    }    catch (Error|RuntimeException localError)    {      throw localError;    }    catch (Throwable localThrowable)    {      throw new UndeclaredThrowableException(localThrowable);    }  }  public final String toString()  {    try    {      return (String)this.h.invoke(this, m2, null);    }    catch (Error|RuntimeException localError)    {      throw localError;    }    catch (Throwable localThrowable)    {      throw new UndeclaredThrowableException(localThrowable);    }  }  public final int hashCode()  {    try    {      return ((Integer)this.h.invoke(this, m0, null)).intValue();    }    catch (Error|RuntimeException localError)    {      throw localError;    }    catch (Throwable localThrowable)    {      throw new UndeclaredThrowableException(localThrowable);    }  }  static  {    try    {      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });      m3 = Class.forName("org.flying.bird.rpc.proxy.UserService").getMethod("test", new Class[0]);      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);      return;    }    catch (NoSuchMethodException localNoSuchMethodException)    {      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());    }    catch (ClassNotFoundException localClassNotFoundException)    {      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());    }  }}

从反编译的结果我们可以知道,jdk动态代理是以反射为基础的,被代理类必须是接口的实现类。jdk首先通过IO流生成相应的class文件,class类实现被代理类接口,继承Proxy父类,,然后在返回对象代理对象的实例。代理对象持有了被代理类的Method对象,通过调用InvocationHandler,this.h.invoke(this, m3, null);执行被代理对象的逻辑。因此,以jdk动态代理为基础的aop实现,A方法调用B方法,只有A方法的aop逻辑会执行是合乎逻辑的,因为我们执行代理对象A方法的时候,其实是执行了原生被代理对象的Method,此Method内部调用了B,因此不会被aop托管


cglib:

public class CglibProxy implements MethodInterceptor {    @Override    public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy proxy)            throws Throwable {     // 添加切面逻辑(advise),此处是在目标类代码执行之前,即为MethodBeforeAdviceInterceptor。          System.out.println("before-------------");          // 执行目标类add方法          proxy.invokeSuper(arg0, arg2);          // 添加切面逻辑(advise),此处是在目标类代码执行之后,即为MethodAfterAdviceInterceptor。          System.out.println("after--------------");          return null;      }}
package org.flying.bird.rpc.proxy.cglib;import org.flying.bird.rpc.proxy.UserServiceImpl;import net.sf.cglib.core.DebuggingClassWriter;import net.sf.cglib.proxy.Enhancer;public class Factory {    /**     * 获得增强之后的目标类,即添加了切入逻辑advice之后的目标类     *      * @param proxy     * @return     */    public static UserServiceImpl getInstance(CglibProxy proxy) {        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,                "C:\\\\Users\\\\nieyanshun\\\\Desktop\\\\test");        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(UserServiceImpl.class);        // 回调方法的参数为代理类对象CglibProxy,最后增强目标类调用的是代理类对象CglibProxy中的intercept方法        enhancer.setCallback(proxy);        UserServiceImpl service = (UserServiceImpl) enhancer.create();        return service;    }    public static void main(String[] args) {        CglibProxy proxy = new CglibProxy();             UserServiceImpl service = Factory.getInstance(proxy);        service.test();    }}

要想知道cglib做了什么,我们还是直接看反编译结果。
另外这里推荐个反编译工具:procyon-decompiler,
java -jar procyon-decompiler-version.jar target.class

// // Decompiled by Procyon v0.5.30// package org.flying.bird.rpc.proxy;import net.sf.cglib.core.Signature;import net.sf.cglib.core.ReflectUtils;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.Callback;import net.sf.cglib.proxy.Factory;public class UserServiceImpl$$EnhancerByCGLIB$$590b218f extends UserServiceImpl implements Factory{    private boolean CGLIB$BOUND;    public static Object CGLIB$FACTORY_DATA;    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;    private static final Callback[] CGLIB$STATIC_CALLBACKS;    private MethodInterceptor CGLIB$CALLBACK_0;    private static Object CGLIB$CALLBACK_FILTER;    private static final Method CGLIB$test$0$Method;    private static final MethodProxy CGLIB$test$0$Proxy;    private static final Object[] CGLIB$emptyArgs;    private static final Method CGLIB$equals$1$Method;    private static final MethodProxy CGLIB$equals$1$Proxy;    private static final Method CGLIB$toString$2$Method;    private static final MethodProxy CGLIB$toString$2$Proxy;    private static final Method CGLIB$hashCode$3$Method;    private static final MethodProxy CGLIB$hashCode$3$Proxy;    private static final Method CGLIB$clone$4$Method;    private static final MethodProxy CGLIB$clone$4$Proxy;    static void CGLIB$STATICHOOK1() {        CGLIB$THREAD_CALLBACKS = new ThreadLocal();        CGLIB$emptyArgs = new Object[0];        final Class<?> forName = Class.forName("org.flying.bird.rpc.proxy.UserServiceImpl$$EnhancerByCGLIB$$590b218f");        final Class<?> forName2;        final Method[] methods = ReflectUtils.findMethods(new String[] { "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;" }, (forName2 = Class.forName("java.lang.Object")).getDeclaredMethods());        CGLIB$equals$1$Method = methods[0];        CGLIB$equals$1$Proxy = MethodProxy.create((Class)forName2, (Class)forName, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");        CGLIB$toString$2$Method = methods[1];        CGLIB$toString$2$Proxy = MethodProxy.create((Class)forName2, (Class)forName, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");        CGLIB$hashCode$3$Method = methods[2];        CGLIB$hashCode$3$Proxy = MethodProxy.create((Class)forName2, (Class)forName, "()I", "hashCode", "CGLIB$hashCode$3");        CGLIB$clone$4$Method = methods[3];        CGLIB$clone$4$Proxy = MethodProxy.create((Class)forName2, (Class)forName, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");        final Class<?> forName3;        CGLIB$test$0$Method = ReflectUtils.findMethods(new String[] { "test", "()V" }, (forName3 = Class.forName("org.flying.bird.rpc.proxy.UserServiceImpl")).getDeclaredMethods())[0];        CGLIB$test$0$Proxy = MethodProxy.create((Class)forName3, (Class)forName, "()V", "test", "CGLIB$test$0");    }    final void CGLIB$test$0() {        super.test();    }    public final void test() {        MethodInterceptor cglib$CALLBACK_2;        MethodInterceptor cglib$CALLBACK_0;        if ((cglib$CALLBACK_0 = (cglib$CALLBACK_2 = this.CGLIB$CALLBACK_0)) == null) {            CGLIB$BIND_CALLBACKS(this);            cglib$CALLBACK_2 = (cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0);        }        if (cglib$CALLBACK_0 != null) {            cglib$CALLBACK_2.intercept((Object)this, UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$test$0$Method, UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$emptyArgs, UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$test$0$Proxy);            return;        }        super.test();    }    final boolean CGLIB$equals$1(final Object o) {        return super.equals(o);    }    public final boolean equals(final Object o) {        MethodInterceptor cglib$CALLBACK_2;        MethodInterceptor cglib$CALLBACK_0;        if ((cglib$CALLBACK_0 = (cglib$CALLBACK_2 = this.CGLIB$CALLBACK_0)) == null) {            CGLIB$BIND_CALLBACKS(this);            cglib$CALLBACK_2 = (cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0);        }        if (cglib$CALLBACK_0 != null) {            final Object intercept = cglib$CALLBACK_2.intercept((Object)this, UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$equals$1$Method, new Object[] { o }, UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$equals$1$Proxy);            return intercept != null && (boolean)intercept;        }        return super.equals(o);    }    final String CGLIB$toString$2() {        return super.toString();    }    public final String toString() {        MethodInterceptor cglib$CALLBACK_2;        MethodInterceptor cglib$CALLBACK_0;        if ((cglib$CALLBACK_0 = (cglib$CALLBACK_2 = this.CGLIB$CALLBACK_0)) == null) {            CGLIB$BIND_CALLBACKS(this);            cglib$CALLBACK_2 = (cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0);        }        if (cglib$CALLBACK_0 != null) {            return (String)cglib$CALLBACK_2.intercept((Object)this, UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$toString$2$Method, UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$emptyArgs, UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$toString$2$Proxy);        }        return super.toString();    }    final int CGLIB$hashCode$3() {        return super.hashCode();    }    public final int hashCode() {        MethodInterceptor cglib$CALLBACK_2;        MethodInterceptor cglib$CALLBACK_0;        if ((cglib$CALLBACK_0 = (cglib$CALLBACK_2 = this.CGLIB$CALLBACK_0)) == null) {            CGLIB$BIND_CALLBACKS(this);            cglib$CALLBACK_2 = (cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0);        }        if (cglib$CALLBACK_0 != null) {            final Object intercept = cglib$CALLBACK_2.intercept((Object)this, UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$hashCode$3$Method, UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$emptyArgs, UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$hashCode$3$Proxy);            return (intercept == null) ? 0 : ((Number)intercept).intValue();        }        return super.hashCode();    }    final Object CGLIB$clone$4() throws CloneNotSupportedException {        return super.clone();    }    protected final Object clone() throws CloneNotSupportedException {        MethodInterceptor cglib$CALLBACK_2;        MethodInterceptor cglib$CALLBACK_0;        if ((cglib$CALLBACK_0 = (cglib$CALLBACK_2 = this.CGLIB$CALLBACK_0)) == null) {            CGLIB$BIND_CALLBACKS(this);            cglib$CALLBACK_2 = (cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0);        }        if (cglib$CALLBACK_0 != null) {            return cglib$CALLBACK_2.intercept((Object)this, UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$clone$4$Method, UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$emptyArgs, UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$clone$4$Proxy);        }        return super.clone();    }    public static MethodProxy CGLIB$findMethodProxy(final Signature signature) {        final String string = signature.toString();        switch (string.hashCode()) {            case -1422510685: {                if (string.equals("test()V")) {                    return UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$test$0$Proxy;                }                break;            }            case -508378822: {                if (string.equals("clone()Ljava/lang/Object;")) {                    return UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$clone$4$Proxy;                }                break;            }            case 1826985398: {                if (string.equals("equals(Ljava/lang/Object;)Z")) {                    return UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$equals$1$Proxy;                }                break;            }            case 1913648695: {                if (string.equals("toString()Ljava/lang/String;")) {                    return UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$toString$2$Proxy;                }                break;            }            case 1984935277: {                if (string.equals("hashCode()I")) {                    return UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$hashCode$3$Proxy;                }                break;            }        }        return null;    }    public UserServiceImpl$$EnhancerByCGLIB$$590b218f() {        CGLIB$BIND_CALLBACKS(this);    }    public static void CGLIB$SET_THREAD_CALLBACKS(final Callback[] array) {        UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$THREAD_CALLBACKS.set(array);    }    public static void CGLIB$SET_STATIC_CALLBACKS(final Callback[] cglib$STATIC_CALLBACKS) {        CGLIB$STATIC_CALLBACKS = cglib$STATIC_CALLBACKS;    }    private static final void CGLIB$BIND_CALLBACKS(final Object o) {        final UserServiceImpl$$EnhancerByCGLIB$$590b218f userServiceImpl$$EnhancerByCGLIB$$590b218f = (UserServiceImpl$$EnhancerByCGLIB$$590b218f)o;        if (!userServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$BOUND) {            userServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$BOUND = true;            Object o2;            if ((o2 = UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$THREAD_CALLBACKS.get()) != null || (o2 = UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$STATIC_CALLBACKS) != null) {                userServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])o2)[0];            }        }    }    public Object newInstance(final Callback[] array) {        CGLIB$SET_THREAD_CALLBACKS(array);        final UserServiceImpl$$EnhancerByCGLIB$$590b218f userServiceImpl$$EnhancerByCGLIB$$590b218f = new UserServiceImpl$$EnhancerByCGLIB$$590b218f();        CGLIB$SET_THREAD_CALLBACKS(null);        return userServiceImpl$$EnhancerByCGLIB$$590b218f;    }    public Object newInstance(final Callback callback) {        CGLIB$SET_THREAD_CALLBACKS(new Callback[] { callback });        final UserServiceImpl$$EnhancerByCGLIB$$590b218f userServiceImpl$$EnhancerByCGLIB$$590b218f = new UserServiceImpl$$EnhancerByCGLIB$$590b218f();        CGLIB$SET_THREAD_CALLBACKS(null);        return userServiceImpl$$EnhancerByCGLIB$$590b218f;    }    public Object newInstance(final Class[] array, final Object[] array2, final Callback[] array3) {        CGLIB$SET_THREAD_CALLBACKS(array3);        switch (array.length) {            case 0: {                final UserServiceImpl$$EnhancerByCGLIB$$590b218f userServiceImpl$$EnhancerByCGLIB$$590b218f = new UserServiceImpl$$EnhancerByCGLIB$$590b218f();                CGLIB$SET_THREAD_CALLBACKS(null);                return userServiceImpl$$EnhancerByCGLIB$$590b218f;            }            default: {                throw new IllegalArgumentException("Constructor not found");            }        }    }    public Callback getCallback(final int n) {        CGLIB$BIND_CALLBACKS(this);        Object cglib$CALLBACK_0 = null;        switch (n) {            case 0: {                cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0;                break;            }            default: {                cglib$CALLBACK_0 = null;                break;            }        }        return (Callback)cglib$CALLBACK_0;    }    public void setCallback(final int n, final Callback callback) {        switch (n) {            case 0: {                this.CGLIB$CALLBACK_0 = (MethodInterceptor)callback;                break;            }        }    }    public Callback[] getCallbacks() {        CGLIB$BIND_CALLBACKS(this);        return new Callback[] { this.CGLIB$CALLBACK_0 };    }    public void setCallbacks(final Callback[] array) {        this.CGLIB$CALLBACK_0 = (MethodInterceptor)array[0];    }    static {        CGLIB$STATICHOOK1();    }}

这里看下test()方法:

public final void test() {        MethodInterceptor cglib$CALLBACK_2;        MethodInterceptor cglib$CALLBACK_0;        if ((cglib$CALLBACK_0 = (cglib$CALLBACK_2 = this.CGLIB$CALLBACK_0)) == null) {            CGLIB$BIND_CALLBACKS(this);            cglib$CALLBACK_2 = (cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0);        }        if (cglib$CALLBACK_0 != null) {            cglib$CALLBACK_2.intercept((Object) this,                    UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$test$0$Method,                    UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$emptyArgs,                    UserServiceImpl$$EnhancerByCGLIB$$590b218f.CGLIB$test$0$Proxy);            return;        }        super.test();    }

其实调用的是MethodInterceptor.intercept方法
方法声明:

public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,                               MethodProxy proxy) throws Throwable;

传递的参数为:

final Class<?> forName3;Method CGLIB$test$0$Method  = ReflectUtils.findMethods(new String[] {"test", "()V"},                (forName3 = Class.forName("org.flying.bird.rpc.proxy.UserServiceImpl"))                        .getDeclaredMethods())[0];
MethodProxy CGLIB$test$0$Proxy = MethodProxy.create((Class) forName3, (Class) forName, "()V", "test",                "CGLIB$test$0");

这里我们发现,cglib的方式和jdk动态代理一样,执行的最终还是MethodInterceptor的方法:

public class CglibProxy implements MethodInterceptor {    @Override    public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy proxy)            throws Throwable {     // 添加切面逻辑(advise),此处是在目标类代码执行之前,即为MethodBeforeAdviceInterceptor。          System.out.println("before-------------");          // 执行目标类add方法          proxy.invokeSuper(arg0, arg2);          // 添加切面逻辑(advise),此处是在目标类代码执行之后,即为MethodAfterAdviceInterceptor。          System.out.println("after--------------");          return null;      }}

这里proxy.invokeSuper(arg0, arg2);的proxy对象为前面生成的MethodProxy,arg0为代理对象。

//这里obj对象为代理对象/**     * Invoke the original (super) method on the specified object.     * @param obj the enhanced object, must be the object passed as the first     * argument to the MethodInterceptor     * @param args the arguments passed to the intercepted method; you may substitute a different     * argument array as long as the types are compatible     * @see MethodInterceptor#intercept     * @throws Throwable the bare exceptions thrown by the called method are passed through     * without wrapping in an <code>InvocationTargetException</code>     */public Object invokeSuper(Object obj, Object[] args) throws Throwable {        try {            init();            FastClassInfo fci = fastClassInfo;            return fci.f2.invoke(fci.i2, obj, args);        } catch (InvocationTargetException e) {            throw e.getTargetException();        }    }

这里就不继续跟踪代码了,从注释就可以看到,这个函数执行了被代理类的逻辑。
即:

public void test() {        System.out.println("UserService 逻辑执行。。。。");    }

Invoke the original (super) method on the specified object.

所以和jdk动态代理一样,cglib实现aop,也会存在B方法被A调用后,只会执行A方法的aop逻辑。

补充一点:从cglib生成的代理类来看public class UserServiceImpl$$EnhancerByCGLIB$$590b218f extends UserServiceImpl implements Factory
是直接继承自被代理对象,所以当父类中方法是final的时候,不能被aop代理。

原创粉丝点击