《Java知識應用》Java CGLib動態代理使用和原理說明


一、CGLib jar包下載

百度網盤:

鏈接:https://pan.baidu.com/s/1O_5o_vtPWEZ3Hy0CHlZDug
提取碼:5wf6

CGLib要使用還需要額外的asm.jar

鏈接:https://pan.baidu.com/s/1874lFlpOLsdzPUs7O9Ol-g
提取碼:wf68 

二、CGLib應用案例

package demo.knowledgepoints.cglib;

public class BaseDemo {

    private String Name;

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    @Override
    public String toString() {
        return "BaseDemo{" +
                "Name='" + Name + '\'' +
                '}';
    }
}
package demo.knowledgepoints.cglib;

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

import java.lang.reflect.Method;

public class MyMethodInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("=============執行自己想要的內容start================");
        System.out.println("method.getName():" + method.getName());
        Object object = methodProxy.invokeSuper(o,objects);
        System.out.println("=============執行自己想要的內容end================");
        return object;
    }
}
package demo.knowledgepoints.cglib;

import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;

public class CGLibTest {

    public static void main(String[] args) {
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "src\\demo\\knowledgepoints\\cglib");

        /**
         * 該類為CGLib設置動態代理的核心,你設置一個怎么樣的動態代理
         */
        Enhancer enhancer = new Enhancer();
        /*******設置需要被代理的類**************/
        enhancer.setSuperclass(BaseDemo.class);
        /*******設置代理類**************/
        enhancer.setCallback(new MyMethodInterceptor());
        /*******創建代理類**************/
        BaseDemo proxyBaseDemo = (BaseDemo)enhancer.create();

        proxyBaseDemo.setName("李磊");

    }
}

運行結果:

這里會出現一個比較有意思的情況,如果是dubug運行會出現如下打印信息

簡單解釋一下:因為IDEA duebug下,你會需要查詢信息,而這些信息其實就是IDEA默認在調用你對象的toString方法。IDEA執行的toString當然也被代理了。

三、CGLib動態代理原理

CGLib動態代理原理和JDK動態原理本質區別很大。

CGLib動態代理原理:是通過子類繼承來實現動態代理的。上面的應用程序我們已經將CGLib的代理類生成到本地:

我們可以看看反編譯后里面的代碼。

public class BaseDemo$$EnhancerByCGLIB$$3c73e677 extends BaseDemo implements Factory{
    final String CGLIB$toString$0() {
        return super.toString();
    }

    public final String toString() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$0$Method, CGLIB$emptyArgs, CGLIB$toString$0$Proxy) : super.toString();
    }

    final String CGLIB$getName$1() {
        return super.getName();
    }

    public final String getName() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        return var10000 != null ? (String)var10000.intercept(this, CGLIB$getName$1$Method, CGLIB$emptyArgs, CGLIB$getName$1$Proxy) : super.getName();
    }

    final void CGLIB$setName$2(String var1) {
        super.setName(var1);
    }

    public final void setName(String var1) {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (this.CGLIB$CALLBACK_0 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            var10000.intercept(this, CGLIB$setName$2$Method, new Object[]{var1}, CGLIB$setName$2$Proxy);
        } else {
            super.setName(var1);
        }
    }
}

上述代碼是我取了其中比較重要的信息,真實代理類,還會多一些代碼。

從上面的文件內容可以看出:

1. 繼承了BaseDemo 

2. 實現Factory 接口,該接口可以創建對象等功能。

3. 重寫了父類方法,並且還是會調用原父類方法。

更多使用方法見CGLib API :http://devdoc.net/javamisc/cglib-3.2.5/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM