博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
静态、动态代理和AOP详解(此坑未填)
阅读量:6805 次
发布时间:2019-06-26

本文共 29863 字,大约阅读时间需要 99 分钟。

静态代理(简单描述)

先定义一个接口,里面定义目标方法

//目标类要实现的接口public interface ITarget {        //目标方法    void doFunc(String words);}

定义一个代理类

public class StaticProxy implements ITarget{        private ITarget target = null;        //关联要增强的目标类    public StaticProxy(ITarget target){        this.target = target;    }     //在这里增强目标类的目标方法    @Override    public void doFunc() {        ...        ...        ...        //增强目标方法        target.doFunc();        ...        ...        ...    }}

以后,任意的一个ITarget接口的子类,都可以注入给StaticProxy类,然后实现一套增强,不再赘述。

动态代理

代理类在程序运行时创建的代理方式被成为 动态代理。也就是说,这种情况下,代理类并不是像静态代理一样,是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。

动态代理是spring AOP的实现原理,spring有两种动态代理模式,cglib和jdk,我们先来将java jdk的动态代理。

jdk的动态代理

首先,我们需要知道,jdk的动态代理只能代理实现了接口的类 没有实现接口的类不能实现JDK动态代理。其次,我们还要了解一个重要的中介接口InvocationHandler,这是jdk的动态代理的基石,它的定义如下:

public interface InvocationHandler {    public Object invoke(Object proxy, Method method, Object[] args)        throws Throwable;}

我们先来写一个jdk的动态代理实例,再来讨论其中的原理吧

jdk动态代理实例

我们先来定义一个目标类,或者说委托类,或者又叫被代理类,它实现了我们上面定义的那个接口ITarget:

public class Entrust implements ITarget {    public void doFunc(String words){        System.out.println(words);    }}

再定义一个中介类,实现InvocationHandler接口,这个中介类,持有被代理的对象,在invoke中利用反射,调用目标类的方法:

public class JdkDynamicProxyHandler
implements InvocationHandler { //invocationHandler持有的被代理对象 T target; public JdkDynamicProxyHandler(T target) { this.target = target; } /** * proxy:代表动态代理对象 * method:代表正在执行的方法 * args:代表调用目标方法时传入的实参 * */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("do before"); Object result = method.invoke(target, args); System.out.println("do after"); return result; }}

好了,我们现在来写一个代理demo:

public static void main(String[] a){        //创建一个实例对象,这个对象是被代理的对象        ITarget attorney = new Attorney();        //创建一个与代理对象相关联的InvocationHandler        InvocationHandler jdkDynamicProxyHandler = new JdkDynamicProxyHandler
(attorney); //创建一个代理对象proxy来代理attorney,代理对象的每个执行方法都会替换执行Invocation中的invoke方法 ITarget proxy = (ITarget) Proxy.newProxyInstance(ITarget.class.getClassLoader(), new Class
[]{ITarget.class}, jdkDynamicProxyHandler); //代理执行上交班费的方法 proxy.doFunc("hello word"); //将生成的代理类写到桌面 writeProxyClassToHardDisk("/home/ls/Desktop/$Proxy22.class"); } public static void writeProxyClassToHardDisk(String path) { byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy22", Attorney.class.getInterfaces()); FileOutputStream out = null; try { out = new FileOutputStream(path); out.write(classFile); out.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } }

最后输出:

clipboard.png

原理剖析

我们来看看Proxy.newProxyInstance方法

public static Object newProxyInstance(ClassLoader loader,                                          Class
[] interfaces, InvocationHandler h) throws IllegalArgumentException { Objects.requireNonNull(h); final Class
[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { //验证一些参数 checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } /* * Look up or generate the designated proxy class. * 从缓存里面获取某个类的代理类,如果该类的代理类不存在,就根据该类的类型创建一个 * 如果要深挖逻辑,可以看看ProxyClassFactory的apply方法。 * 其实生成代理类字节码文件的工作是通过 ProxyGenerate类中的generateProxyClass方法来完成的。 */ Class
cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler. * * /** parameter types of a proxy class constructor */ * private static final Class
[] constructorParams = { InvocationHandler.class }; * */ try { if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } //看上面的注释,constructorParams={ InvocationHandler.class }, //这是在生成代理类的构造函数,获得一个参数为InvocationHandler的构造方法 final Constructor
cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction
() { public Void run() { cons.setAccessible(true); return null; } }); } //这行代码的意思是将h,也就是实现InvocationHandler的实现类, //我们传入的是jdkDynamicProxyHandler,注入到cons中。 //然后newInstance生成一个已经组装过参数的代理类。 return cons.newInstance(new Object[]{h}); } catch (IllegalAccessException|InstantiationException e) { throw new InternalError(e.toString(), e); } catch (InvocationTargetException e) { Throwable t = e.getCause(); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new InternalError(t.toString(), t); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } }

我们最应该关注的是 Class<?> cl = getProxyClass0(loader, intfs);这句,这里产生了代理类,后面代码中的构造器也是通过这里产生的类来获得,可以看出,这个类的产生就是整个动态代理的关键,由于是动态生成的类文件,我这里不具体进入分析如何产生的这个类文件,只需要知道这个类文件时缓存在java虚拟机中的。

我们对这个代理类进行反编译:(本次使用)

import java.lang.reflect.UndeclaredThrowableException;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import aopLearn.ITarget;import java.lang.reflect.Proxy;// // Decompiled by Procyon v0.5.30// public final class $Proxy22 extends Proxy implements ITarget{    private static Method m1;    private static Method m3;    private static Method m2;    private static Method m0;    /**      *注意这里是生成代理类的构造方法,方法参数为InvocationHandler类型,看到这,是不是就有点明白了      *为何代理对象调用方法都是执行InvocationHandler中的invoke方法,而InvocationHandler又持有一个      *被代理对象的实例      *      *super(paramInvocationHandler),是调用父类Proxy的构造方法。      *父类持有:protected InvocationHandler h;      *Proxy构造方法:      *    protected Proxy(InvocationHandler h) {      *         Objects.requireNonNull(h);      *         this.h = h;      *     }      *      */    public $Proxy22(final InvocationHandler invocationHandler) {        super(invocationHandler);    }        //这个静态块本来是在最后的,我把它拿到前面来,方便描述    static {        try {            //doFunc通过反射得到的名字m3            $Proxy22.m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));            $Proxy22.m3 = Class.forName("aopLearn.ITarget").getMethod("doFunc", Class.forName("java.lang.String"));            $Proxy22.m2 = Class.forName("java.lang.Object").getMethod("toString", (Class
[])new Class[0]); $Proxy22.m0 = Class.forName("java.lang.Object").getMethod("hashCode", (Class
[])new Class[0]); } catch (NoSuchMethodException ex) { throw new NoSuchMethodError(ex.getMessage()); } catch (ClassNotFoundException ex2) { throw new NoClassDefFoundError(ex2.getMessage()); } } public final boolean equals(final Object o) { try { return (boolean)super.h.invoke(this, $Proxy22.m1, new Object[] { o }); } catch (Error | RuntimeException error) { throw; } catch (Throwable t) { throw new UndeclaredThrowableException(t); } } /** * *这里调用代理对象的doFunc方法,直接就调用了InvocationHandler中的invoke方法,并把m3传了进去。 *this.h.invoke(this, m3, null);这里简单,明了。 *代理对象持有一个InvocationHandler对象,InvocationHandler对象持有一个被代理的对象, *再联系到InvacationHandler中的invoke方法。其实就是代理对象调用InvocationHandler, * InvocationHandler对象反射调用委托类对象。 */ public final void doFunc(final String s) { try { super.h.invoke(this, $Proxy22.m3, new Object[] { s }); } catch (Error | RuntimeException error) { throw; } catch (Throwable t) { throw new UndeclaredThrowableException(t); } } public final String toString() { try { return (String)super.h.invoke(this, $Proxy22.m2, null); } catch (Error | RuntimeException error) { throw; } catch (Throwable t) { throw new UndeclaredThrowableException(t); } } public final int hashCode() { try { return (int)super.h.invoke(this, $Proxy22.m0, null); } catch (Error | RuntimeException error) { throw; } catch (Throwable t) { throw new UndeclaredThrowableException(t); } } }

看完了这些,我们来想一下,为什么jdk的动态代理,一定要委托类实现一个接口?这是因为我们可以看到,我们生成的代理类Proxy22 extends Proxy implements ITarget,已经继承了Proxy类,而java中不能多继承,为了让$Proxy22和委托类建立联系,只能实现一个接口。这里的建立联系,是指通过接口,得到委托类方法的反射等,并且,委托类实现自接口的方法,才能被增强

故而,本质上来说,jdk的动态代理,是为接口产生代理

在spring AOP中,我们使用jdk动态代理时当然也要定义InvocationHandler的实现类对象,spring中的是org.springframework.aop.framework.JdkDynamicAopProxy类。

cglib的动态代理

cglib的动态代理针对类来实现代理,对指定目标产生一个子类 通过方法拦截技术拦截所有父类方法的调用。我们要使用cglib代理必须引入cglib的jar包。

cglib动态代理实例

同样,定义一个跟上面例子一样的委托类。

public class Entrust {    public void doFunc(String words){        System.out.println(words);    }}

实现MethodInterceptor接口生成方法拦截器

public class EntrustInterceptor implements MethodInterceptor{    @Override    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {        System.out.println("before");        Object o = proxy.invokeSuper(obj,args);        System.out.println("after");        return o;    }}

实例如下:

public static void main(String[] a){    //cglib自带的debug工具,可以将代理类输出到指定路径    System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/home/ls/Desktop/cglib");    Enhancer enhancer = new Enhancer();    //继承被代理类    enhancer.setSuperclass(Entrust.class);    enhancer.setCallback(new EntrustInterceptor());    //生成的代理类对象    Entrust entrust = (Entrust) enhancer.create();    //在调用我们代理类中的方法时会被我们实现的方法拦截器拦截    entrust.doFunc("hello word");}

输出结果如下:

clipboard.png

原理剖析

CGLIB会让生成的代理类继承被代理类,并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。在CGLIB底层,其实是借助了ASM这个非常强大的Java字节码生成框架。

我们看到,代理类对象是由Enhancer类创建的。Enhancer是CGLIB的字节码增强器,可以很方便的对类进行拓展,创建代理对象的几个步骤:

  1. 生成代理类的二进制字节码文件;
  2. 加载二进制字节码,生成Class对象( 例如使用Class.forName()方法 );
  3. 通过反射机制获得实例构造,并创建代理类对象

我们来看看将代理类Class文件反编译之后的Java代码,一个动态代理,产生了三个类:

clipboard.png

主要的代理类是

Entrust$$EnhancerByCGLIB$$832e20ab
// // Decompiled by Procyon v0.5.30// package com.lufax.util.aopCache.cglibProxy;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;/** * 生成的代理类Entrust$$EnhancerByCGLIB$$832e20ab继承被代理类Entrust。 * 在这里我们需要注意一点:如果委托类被final修饰,那么它不可被继承,即不可被代理; * 同样,如果委托类中存在final修饰的方法,那么该方法也不可被代理; *  */public class Entrust$$EnhancerByCGLIB$$832e20ab extends Entrust implements Factory{    private boolean CGLIB$BOUND;    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;    private static final Callback[] CGLIB$STATIC_CALLBACKS;    private MethodInterceptor CGLIB$CALLBACK_0;    private static final Method CGLIB$doFunc$0$Method;    private static final MethodProxy CGLIB$doFunc$0$Proxy;    private static final Object[] CGLIB$emptyArgs;    private static final Method CGLIB$finalize$1$Method;    private static final MethodProxy CGLIB$finalize$1$Proxy;    private static final Method CGLIB$equals$2$Method;    private static final MethodProxy CGLIB$equals$2$Proxy;    private static final Method CGLIB$toString$3$Method;    private static final MethodProxy CGLIB$toString$3$Proxy;    private static final Method CGLIB$hashCode$4$Method;    private static final MethodProxy CGLIB$hashCode$4$Proxy;    private static final Method CGLIB$clone$5$Method;    private static final MethodProxy CGLIB$clone$5$Proxy;        static void CGLIB$STATICHOOK1() {        CGLIB$THREAD_CALLBACKS = new ThreadLocal();        CGLIB$emptyArgs = new Object[0];        final Class
forName = Class.forName("com.lufax.util.aopCache.cglibProxy.Entrust$$EnhancerByCGLIB$$832e20ab"); final Class
forName2; final Method[] methods = ReflectUtils.findMethods(new String[] { "finalize", "()V", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;" }, (forName2 = Class.forName("java.lang.Object")).getDeclaredMethods()); CGLIB$finalize$1$Method = methods[0]; CGLIB$finalize$1$Proxy = MethodProxy.create((Class)forName2, (Class)forName, "()V", "finalize", "CGLIB$finalize$1"); CGLIB$equals$2$Method = methods[1]; CGLIB$equals$2$Proxy = MethodProxy.create((Class)forName2, (Class)forName, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2"); CGLIB$toString$3$Method = methods[2]; CGLIB$toString$3$Proxy = MethodProxy.create((Class)forName2, (Class)forName, "()Ljava/lang/String;", "toString", "CGLIB$toString$3"); CGLIB$hashCode$4$Method = methods[3]; CGLIB$hashCode$4$Proxy = MethodProxy.create((Class)forName2, (Class)forName, "()I", "hashCode", "CGLIB$hashCode$4"); CGLIB$clone$5$Method = methods[4]; CGLIB$clone$5$Proxy = MethodProxy.create((Class)forName2, (Class)forName, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5"); final Class
forName3; CGLIB$doFunc$0$Method = ReflectUtils.findMethods(new String[] { "doFunc", "(Ljava/lang/String;)V" }, (forName3 = Class.forName("com.lufax.util.aopCache.cglibProxy.Entrust")).getDeclaredMethods())[0]; CGLIB$doFunc$0$Proxy = MethodProxy.create((Class)forName3, (Class)forName, "(Ljava/lang/String;)V", "doFunc", "CGLIB$doFunc$0"); } //代理类会为委托方法生成两个方法,一个是重写的doFunc方法, //另一个是CGLIB$doFunc$0方法,我们可以看到它是直接调用父类的doFunc方法; final void CGLIB$doFunc$0(final String s) { super.doFunc(s); } //当执行代理对象的doFunc方法时,会首先判断一下是否存在实现了MethodInterceptor接口的CGLIB$CALLBACK_0; //如果存在,则将调用MethodInterceptor中的intercept方法,如图2.1。 public final void doFunc(final String s) { 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) { //这里开始调用我们定义的EntrustInterceptor中的intercept方法。 //参数1、代理对象;2、委托类方法;3、方法参数;4、代理方法的MethodProxy对象(注意这个对象)。 cglib$CALLBACK_2.intercept((Object)this, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$doFunc$0$Method, new Object[] { s }, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$doFunc$0$Proxy); return; } super.doFunc(s); } final void CGLIB$finalize$1() throws Throwable { super.finalize(); } protected final void finalize() throws Throwable { 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, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$finalize$1$Method, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$emptyArgs, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$finalize$1$Proxy); return; } super.finalize(); } final boolean CGLIB$equals$2(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, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$equals$2$Method, new Object[] { o }, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$equals$2$Proxy); return intercept != null && (boolean)intercept; } return super.equals(o); } final String CGLIB$toString$3() { 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, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$toString$3$Method, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$emptyArgs, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$toString$3$Proxy); } return super.toString(); } final int CGLIB$hashCode$4() { 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, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$hashCode$4$Method, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$emptyArgs, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$hashCode$4$Proxy); return (intercept == null) ? 0 : ((Number)intercept).intValue(); } return super.hashCode(); } final Object CGLIB$clone$5() 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, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$clone$5$Method, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$emptyArgs, Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$clone$5$Proxy); } return super.clone(); } public static MethodProxy CGLIB$findMethodProxy(final Signature signature) { final String string = signature.toString(); switch (string.hashCode()) { case -1574182249: { if (string.equals("finalize()V")) { return Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$finalize$1$Proxy; } break; } case -508378822: { if (string.equals("clone()Ljava/lang/Object;")) { return Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$clone$5$Proxy; } break; } case 346793840: { if (string.equals("doFunc(Ljava/lang/String;)V")) { return Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$doFunc$0$Proxy; } break; } case 1826985398: { if (string.equals("equals(Ljava/lang/Object;)Z")) { return Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$equals$2$Proxy; } break; } case 1913648695: { if (string.equals("toString()Ljava/lang/String;")) { return Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$toString$3$Proxy; } break; } case 1984935277: { if (string.equals("hashCode()I")) { return Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$hashCode$4$Proxy; } break; } } return null; } public Entrust$$EnhancerByCGLIB$$832e20ab() { CGLIB$BIND_CALLBACKS(this); } public static void CGLIB$SET_THREAD_CALLBACKS(final Callback[] array) { Entrust$$EnhancerByCGLIB$$832e20ab.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 Entrust$$EnhancerByCGLIB$$832e20ab entrust$$EnhancerByCGLIB$$832e20ab = (Entrust$$EnhancerByCGLIB$$832e20ab)o; if (!entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$BOUND) { entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$BOUND = true; Object o2; if ((o2 = Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$THREAD_CALLBACKS.get()) != null || (o2 = Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$STATIC_CALLBACKS) != null) { entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])o2)[0]; } } } public Object newInstance(final Callback[] array) { CGLIB$SET_THREAD_CALLBACKS(array); final Entrust$$EnhancerByCGLIB$$832e20ab entrust$$EnhancerByCGLIB$$832e20ab = new Entrust$$EnhancerByCGLIB$$832e20ab(); CGLIB$SET_THREAD_CALLBACKS(null); return entrust$$EnhancerByCGLIB$$832e20ab; } public Object newInstance(final Callback callback) { CGLIB$SET_THREAD_CALLBACKS(new Callback[] { callback }); final Entrust$$EnhancerByCGLIB$$832e20ab entrust$$EnhancerByCGLIB$$832e20ab = new Entrust$$EnhancerByCGLIB$$832e20ab(); CGLIB$SET_THREAD_CALLBACKS(null); return entrust$$EnhancerByCGLIB$$832e20ab; } public Object newInstance(final Class[] array, final Object[] array2, final Callback[] array3) { CGLIB$SET_THREAD_CALLBACKS(array3); switch (array.length) { case 0: { final Entrust$$EnhancerByCGLIB$$832e20ab entrust$$EnhancerByCGLIB$$832e20ab = new Entrust$$EnhancerByCGLIB$$832e20ab(); CGLIB$SET_THREAD_CALLBACKS(null); return entrust$$EnhancerByCGLIB$$832e20ab; } 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(); }}

逻辑进入到我们在EntrustInterceptor 中定义的intercept方法

@Override    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {        System.out.println("before");        Object o = proxy.invokeSuper(obj,args);        System.out.println("after");        return o;    }

我们看看MethodProxy的invokeSuper方法:

/**     * 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 InvocationTargetException     */    public Object invokeSuper(Object obj, Object[] args) throws Throwable {        try {            init();            FastClassInfo fci = fastClassInfo;            //f2是由CGlib生成的,在输出的class中有这个类。            //它就是Entrust$$EnhancerByCGLIB$$832e20ab$$FastClassByCGLIB$$817a77c.class            return fci.f2.invoke(fci.i2, obj, args);        } catch (InvocationTargetException e) {            throw e.getTargetException();        }    }

我们把

Entrust$$EnhancerByCGLIB$$832e20ab$$FastClassByCGLIB$$817a77c.class

也反编译出来,然后贴出invoke方法,注意case14调用了

entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$doFunc$0((String)array[0]);:
public Object invoke(final int n, final Object o, final Object[] array) throws InvocationTargetException {        final Entrust$$EnhancerByCGLIB$$832e20ab entrust$$EnhancerByCGLIB$$832e20ab = (Entrust$$EnhancerByCGLIB$$832e20ab)o;        try {            switch (n) {                case 0: {                    entrust$$EnhancerByCGLIB$$832e20ab.setCallbacks((Callback[])array[0]);                    return null;                }                case 1: {                    Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$SET_STATIC_CALLBACKS((Callback[])array[0]);                    return null;                }                case 2: {                    Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$SET_THREAD_CALLBACKS((Callback[])array[0]);                    return null;                }                case 3: {                    return entrust$$EnhancerByCGLIB$$832e20ab.getCallback(((Number)array[0]).intValue());                }                case 4: {                    return entrust$$EnhancerByCGLIB$$832e20ab.getCallbacks();                }                case 5: {                    entrust$$EnhancerByCGLIB$$832e20ab.doFunc((String)array[0]);                    return null;                }                case 6: {                    entrust$$EnhancerByCGLIB$$832e20ab.setCallback(((Number)array[0]).intValue(), (Callback)array[1]);                    return null;                }                case 7: {                    return Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$findMethodProxy((Signature)array[0]);                }                case 8: {                    Entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$STATICHOOK1();                    return null;                }                case 9: {                    entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$finalize$1();                    return null;                }                case 10: {                    return entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$toString$3();                }                case 11: {                    return new Integer(entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$hashCode$4());                }                case 12: {                    return entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$clone$5();                }                case 13: {                    return new Boolean(entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$equals$2(array[0]));                }                case 14: {                    entrust$$EnhancerByCGLIB$$832e20ab.CGLIB$doFunc$0((String)array[0]);                    return null;                }                case 15: {                    return new Boolean(entrust$$EnhancerByCGLIB$$832e20ab.equals(array[0]));                }                case 16: {                    return entrust$$EnhancerByCGLIB$$832e20ab.toString();                }                case 17: {                    return new Integer(entrust$$EnhancerByCGLIB$$832e20ab.hashCode());                }                case 18: {                    return entrust$$EnhancerByCGLIB$$832e20ab.newInstance((Callback)array[0]);                }                case 19: {                    return entrust$$EnhancerByCGLIB$$832e20ab.newInstance((Class[])array[0], (Object[])array[1], (Callback[])array[2]);                }                case 20: {                    return entrust$$EnhancerByCGLIB$$832e20ab.newInstance((Callback[])array[0]);                }                case 21: {                    Entrust.main((String[])array[0]);                    return null;                }                case 22: {                    entrust$$EnhancerByCGLIB$$832e20ab.wait(((Number)array[0]).longValue(), ((Number)array[1]).intValue());                    return null;                }                case 23: {                    entrust$$EnhancerByCGLIB$$832e20ab.wait(((Number)array[0]).longValue());                    return null;                }                case 24: {                    entrust$$EnhancerByCGLIB$$832e20ab.wait();                    return null;                }                case 25: {                    return entrust$$EnhancerByCGLIB$$832e20ab.getClass();                }                case 26: {                    entrust$$EnhancerByCGLIB$$832e20ab.notify();                    return null;                }                case 27: {                    entrust$$EnhancerByCGLIB$$832e20ab.notifyAll();                    return null;                }            }        }        catch (Throwable t) {            throw new InvocationTargetException(t);        }        throw new IllegalArgumentException("Cannot find matching method/constructor");    }

事实证明,最后确实是进入了case14,调用了代理类的代理doFunc方法,最后再回到EntrustInterceptor.invoke中。完成逻辑

Spring AOP

未完待续

转载地址:http://qynwl.baihongyu.com/

你可能感兴趣的文章
java反射
查看>>
用Chrome 浏览器调试移动端网页 chrome://inspect/#devices
查看>>
js中页面加载完成后执行的几种方式及执行顺序
查看>>
移动端 --- 布局
查看>>
关于Myeclipse自带JDK与本机安装JDK的的区别
查看>>
$(document) 和 $(e.target)实现div的显示和隐藏
查看>>
转 Python多版本管理-pyenv
查看>>
C#异步编程
查看>>
html5,表单的综合案例
查看>>
tableView
查看>>
git 入门 1
查看>>
BZOJ1432: [ZJOI2009]Function
查看>>
CSMA/CD工作原理
查看>>
Torch7在Ubuntu下的安装与配置
查看>>
铁大好青年一队绩效评价
查看>>
Markdon 作图语法 CSDN
查看>>
超越最常用的快捷键
查看>>
GYOJ_1812_股票(stock)
查看>>
cn microsoft hyper-v server 2016 安装笔记
查看>>
windows的cmd模式下目录名称中有空格
查看>>