JAVA基礎——使用cglib實現動態代理

JAVA 代理模式

​ 簡而言之,代理是一種通過創建代理對象的方式,從而實現對被代理對象實現功能增強的一種方式,JAVA 中有靜態和動態兩種代理,動態代理又可以分爲基於接口的動態代理(JDK 實現)和基於子類的動態代理(cglib 實現),這裏我們講解基於子類的動態代理

基於子類的動態代理(cglib 實現的動態代理)

​ 使用代理的好處就是在不修改原代碼的基礎上可以實現對原方法的增強,使用JDK官方的動態代理主要是依靠Proxy類,這種方法實現的動態代理要求被代理類至少實現一個接口,沒有實現接口的類是不能被代理的

​ 那麼沒有實現接口或者不需要實現接口的類,我們怎麼對它進行代理呢?

​ 通過引入第三方cglib庫,我們可以實現基於子類的動態代理,使用cglib實現的動態代理也有一個約束條件,就是被代理類不能是最終類

​ 使用cglib實現的動態代理核心是Enhancer類,其實實現的過程和JDK實現動態代理的過程極其類似

導入 jar 包

​ 我是用的是maven工程,所以第一步是要導入cglib的 jar 包,當然手動導入也沒有問題,pom.xml文件配置如下:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.1_3</version>
</dependency>

編寫被代理類

​ 我這裏被代理類主要就實現一個賣東西的功能,之後我們會通過代理類對被代理類中的方法進行增強操作:

package com.lmh.cglib;

import com.lmh.proxy.IPorducer;

/**
 * 生產者
 */
public class Producer {
    public void saleProduct(float money) {
        System.out.println("銷售產品,拿到錢 " + money);
    }
}

編寫代理類(這裏也是一個測試類)

​ 這一步是整個過程的關鍵,代理類的實現要通過Enhancer類,我們需要通過Enhancer類中的create方法創建一個代理對象,具體實現方法如下,作用是給售價打八折,後面我會詳細的解釋各部分的功能

package com.lmh.cglib;

import com.lmh.proxy.IPorducer;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 模擬一個消費者
 */
public class Client {
    public static void main(String[] args) {
        Producer producer = new Producer();
        Producer enhancerProducer = (Producer) Enhancer.create(producer.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                // 提供增強代碼
                Object returnValue = null;
                Float money = (Float) objects[0];
                if ("saleProduct".equals(method.getName())) {
                    returnValue = method.invoke(producer, money * 0.8f);
                }
                return returnValue;
            }
        });
        enhancerProducer.saleProduct(1000f);
    }
}

​ 這裏我們可以看到,enhancerProducer就是我們創建的代理對象,這個對象可以執行被代理類中所有的方法,並且我們可以在代理對象中對被代理類的方法進行增強,這裏使用了強轉,因爲create方法的返回值是Object類型的對象

create方法有兩個參數,分別是Class typeCallback callback,其中Class type是值被代理類的字節碼文件,這是固定的,因爲有了被代理類的字節碼後,就相當於可以獲取被代理類的全部信息;Callback callback是用於提供增強代碼的,一般都是寫一個接口的實現,通常情況下都是匿名內部類,這裏我們一般不適用Callback接口,而是使用它的子接口實現類MethodInterceptor

MethodInterceptor接口需要重寫intercept方法,intercept方法中的內容即爲對被代理類的增強,該方法有四個參數:Object oMethod methodObject[] objectsMethodProxy methodProxy

Object o參數,是一個代理對象的引用,Method method是當前執行,即被攔截的被代理類方法,Objects[] objects是當前執行方法所用的參數,索引順序即爲方法定義時參數的順序,MethodProxy methodProxy指的是當前執行的方法的代理對象

​ 通過向上述代碼一樣編寫,我們就可以實現對被代理類功能的增強!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章