Spring動態代理和cglib代理實現

1.基於jdk動態代理實現方式

/**
 * 模擬一個消費者
 */
public class Client {

    public static void main(String[] args) {
        final Producer producer = new Producer();

        /**
         * 動態代理:
         *  特點:字節碼隨用隨創建,隨用隨加載
         *  作用:不修改源碼的基礎上對方法增強
         *  分類:
         *      基於接口的動態代理
         *      基於子類的動態代理
         *  基於接口的動態代理:
         *      涉及的類:Proxy
         *      提供者:JDK官方
         *  如何創建代理對象:
         *      使用Proxy類中的newProxyInstance方法
         *  創建代理對象的要求:
         *      被代理類最少實現一個接口,如果沒有則不能使用
         *  newProxyInstance方法的參數:
         *      ClassLoader:類加載器
         *          它是用於加載代理對象字節碼的。和被代理對象使用相同的類加載器。固定寫法。
         *      Class[]:字節碼數組
         *          它是用於讓代理對象和被代理對象有相同方法。固定寫法。
         *      InvocationHandler:用於提供增強的代碼
         *          它是讓我們寫如何代理。我們一般都是些一個該接口的實現類,通常情況下都是匿名內部類,但不是必須的。
         *          此接口的實現類都是誰用誰寫。
         */
       IProducer proxyProducer = (IProducer) Proxy.newProxyInstance(producer.getClass().getClassLoader(),
                producer.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     * 作用:執行被代理對象的任何接口方法都會經過該方法
                     * 方法參數的含義
                     * @param proxy   代理對象的引用
                     * @param method  當前執行的方法
                     * @param args    當前執行方法所需的參數
                     * @return        和被代理對象方法有相同的返回值
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) 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;
                    }
                });

       String result =  proxyProducer.saleProduct(10000f);
       System.out.println(result);
    }
}
/**
 * 一個生產者
 */
public class Producer implements IProducer{

    /**
     * 銷售
     * @param money
     */
    public String saleProduct(float money){
        System.out.println("銷售產品,並拿到錢:"+money);
        return money+"";
    }

}

 

 


 

2.1.基於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(12000f);
    }
}
/**
 * 一個生產者
 */
public class Producer {

    /**
     * 銷售
     * @param money
     */
    public void saleProduct(float money){
        System.out.println("銷售產品,並拿到錢:"+money);
    }
}

 

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