1. 程式人生 > 實用技巧 >動態代理常用的有兩種方式

動態代理常用的有兩種方式

一、JDK代理

public class Client {
public static void main(String[] args) {

    final Product product = new Product();

    /**
     * 動態代理:
     *      特點:位元組碼隨用隨建立,隨用隨載入
     *      作用: 不修改原始碼的基礎上對方法進行增強
     *
     * 分類:
     *      基於介面的動態代理(一個是實現)
     *      基於子類的動態代理(一個是繼承)
     * 基於介面的動態代理:
     *      涉及的類:proxy
     *      提供方:JDK官方
     * 怎麼樣建立代理物件:
     *      使用proxy類中的newProxyInstance
     *
     * 建立代理物件的要求“
     *      被代理類最少要實現一個介面,如果沒有則不能使用
     *
     * newProxyInstance方法的引數:
     *      ClassLoader:類載入器(被代理物件)
     *          作用:用於載入代理物件位元組碼的。和被代理物件使用相同的類載入器。固定寫法
     *      Class[]:位元組碼陣列
     *          作用:用於讓代理物件和被代理物件有相同方法。固定寫法。
     *      InvocationHandler:用於提供增強的程式碼
     *
     */

    ProductInterface proxyProduct = (ProductInterface) Proxy.newProxyInstance(product.getClass().getClassLoader(),
            product.getClass().getInterfaces(),
            new InvocationHandler() {
                /**
                 * 作用:執行被代理物件實現介面的所有方法都會經過invoke()方法
                 *
                 * @param proxy  被代理物件
                 * @param method 當前執行的方法
                 * @param args   當前執行方法所需的引數
                 * @return       和被代理物件方法有相同的返回值
                 * @throws Throwable
                 */
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    //提供增強的程式碼

                    Object returnValue = null;

                    //1.獲取方法執行的引數
                    Float money = (Float) args[0];
                    if("saleProduct".equals( method.getName())){
                        returnValue = method.invoke(product, money * 0.8f);
                    }
                    return returnValue;
                }
            });

    proxyProduct.saleProduct(1000);

}

}

二、Cglib代理

public class Client {
public static void main(String[] args) {

    final Producer producer = new Producer();

    /**
     * 動態代理:
     *      特點:位元組碼隨用隨建立,隨用隨載入
     *      作用: 不修改原始碼的基礎上對方法進行增強
     *
     * 分類:
     *      基於介面的動態代理
     *      基於子類的動態代理
     * 基於介面的動態代理:
     *      涉及的類:Enhancer
     *      提供方:cglib第三方包
     * 怎麼樣建立代理物件:
     *      使用Enhancer中的create()方法
     *
     * 建立代理物件的要求“
     *      被代理類不是最終類,因為不是最終類才有子類才能被代理
     *
     * create方法的引數
     *      Class:位元組碼
     *          它是用於指定被代理物件的位元組碼。
     *
     *      Callback:用於提供增強的程式碼
     *          我們一般寫的都是該介面的子介面實現類:MethodInterceptor
     *
     */
    Producer cglibProducer = (Producer)Enhancer.create(producer.getClass(), new MethodInterceptor() {
        /**
         * 執行北地阿里物件的任何方法都會經過該方法
         * @param proxy
         * @param method
         * @param args
         *    以上三個引數和基於介面的動態代理中invoke方法的引數是一樣的
         * @param methodProxy :當前執行方法的代理物件
         * @return
         * @throws Throwable
         */
        @Override
        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            //提供增強的程式碼
            Object returnValue = null;

            //1.獲取方法執行的引數
            Float money = (Float)args[0];
            //2.判斷當前方法是不是銷售
            if("saleProduct".equals(method.getName())) {
                returnValue = method.invoke(producer, money*0.8f);
            }
            return returnValue;
        }
    });
    cglibProducer.saleProduct(1000f);
      }
  }