1. 程式人生 > >Spring(六)動態代理

Spring(六)動態代理

AR throws 介紹 自己的 根據 spring implement ret new

在上一篇博客中簡單寫了一下靜態代理,這裏主要講一下動態代理

動態代理主要有兩種

JDK動態代理 CGLIB動態代理

那這兩種代理有什麽區別呢?

(根據自己的理解總結)

1.JDK動態代理

他的特點是:目標對象必須有接口

他的實質是:創建了接口的一個實現類

他運行的時機:程序運行時

2.CGLIB動態代理

他的特點是:在一個類型沒有接口的情況下進行代理

他的實質是:在內存中構建目標類型的子類

他運行的時機是:編譯時

簡單介紹完這兩種代理後,就用個例子具體看怎麽實現動態代理

先做JDK動態代理

準備一個接口ISomeService,接口中有一個方法doSome(),和一個這個接口的實現類SomeServiceImpl,並重寫其中的方法,具體代碼如下

技術分享圖片
package demo15;

/**
 * Created by mycom on 2018/3/8.
 */
public interface ISomeService
{
    public void doSome();
}
技術分享圖片 技術分享圖片
package demo15;

/**
 * Created by mycom on 2018/3/8.
 */
public class SomeServiceImpl implements ISomeService {
    public void doSome() {
        System.out.println("十點十分的復習");
    }
}
技術分享圖片

使用JDK動態代理不需要再配置文件中進行配置,所以現在直接進行測試,但是測試的時候不能使用單測,而是使用main方法進行測試

技術分享圖片
package demo15;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by mycom on 2018/3/8.
 */
public class Test {
    public static void main(String[] args) {
        //首先創建一個接口的實現類
        final SomeServiceImpl service=new SomeServiceImpl();
        //在調用方法之前想使用動態代理記錄一下日誌,生成動態代理,返回的是接口
        ISomeService proxyInstance =(ISomeService) Proxy.newProxyInstance(service.getClass().getClassLoader(),
                service.getClass().getInterfaces(), new InvocationHandler() {
                    /**
                     *
                     * @param proxy  代理對象
                     * @param method  目標類型的方法
                     * @param args  方法的參數
                     * @return
                     * @throws Throwable
                     */
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //在這裏記錄一下日誌
                        System.out.println("before=====");
                        //調用method 的
                        method.invoke(service,args);//相當於執行目標類型的方法
                        System.out.println("after=======");
                        return null;
                    }
                });

        //調用動態代理中的方法中的方法
        proxyInstance.doSome();
    }
}
技術分享圖片

運行的結果如下

技術分享圖片

這說明運行時先執行了invoke方法,再執行接口中doSome的方法,實驗成功!

使用CGLIB動態代理實現上述中的運行結果,如何實現呢?

這時就不用再創建接口了,(在這裏我就使用上面的SomeServiceImpl這個類了,這個類中不用做改動),我直接進行測試了,測試還和上面一樣,使用main方法測試,不用配置文件

技術分享圖片
package demo09;


import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * Created by mycom on 2018/3/8.
 */
public class Test {
    public static void main(String[] args) {
        final SomeServiceImpl service=new SomeServiceImpl();
        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(service.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            /**
             *
             * @param o 代理對象
             * @param method 目標類型的方法
             * @param objects 目標方法的參數
             * @param methodProxy 代理類的方法   是一個新的參數
             * @return
             * @throws Throwable
             */
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("before=====");
                methodProxy.invoke(service,objects);
                System.out.println("after=====");
                return null;
            }
        });
        SomeServiceImpl proxy =(SomeServiceImpl) enhancer.create();
        proxy.doSome();
    }
}
技術分享圖片

運行結果和上面的一樣,這就是兩種方法實現動態代理!

Spring(六)動態代理