靜態、動態代理和AOP詳解(此坑未填)

靜態代理(簡單描述)

先定義一個接口,裏面定義目標方法java

//目標類要實現的接口
public interface ITarget {
    
    //目標方法
    void doFunc(String words);
}

定義一個代理類spring

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代碼中的「指示」動態生成的。app

動態代理是spring AOP的實現原理,spring有兩種動態代理模式,cglib和jdk,咱們先來將java jdk的動態代理。框架

jdk的動態代理

首先,咱們須要知道,jdk的動態代理只能代理實現了接口的類 沒有實現接口的類不能實現JDK動態代理。其次,咱們還要了解一個重要的中介接口InvocationHandler,這是jdk的動態代理的基石,它的定義以下:ide

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中利用反射,調用目標類的方法:ui

public class JdkDynamicProxyHandler<T>  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:this

public static void main(String[] a){
        //建立一個實例對象,這個對象是被代理的對象
        ITarget attorney = new Attorney();

        //建立一個與代理對象相關聯的InvocationHandler
        InvocationHandler jdkDynamicProxyHandler = new JdkDynamicProxyHandler<ITarget>(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<Void>() {
                    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虛擬機中的。

咱們對這個代理類進行反編譯:(本次使用http://www.javadecompilers.co...

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方法。
            //參數一、代理對象;二、委託類方法;三、方法參數;四、代理方法的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 <code>InvocationTargetException</code>
     */
    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

未完待續

相關文章
相關標籤/搜索