設計模式-代理模式

  • 靜態代理
  • 動態代理 - jdk代理
  • 動態代理 - cglib代理
定義Person接口對象
public interface Person {
    public void invoke();
}
定義Student對象實現Person
@Slf4j
public class Student implements Person{
    @Override
    public void invoke() {
        log.info("學生處理事情...");
    }
}

1.靜態代理的實現

  1. 靜態代理類要實現被代理對象接口
  2. 被代理對象接口作爲靜態代理類的屬性
  3. 被代理對象作爲靜態代理類的構造函數入參傳入
  4. new PersonProxy()
@Slf4j
public class PersonProxy implements Person{

    private Person person;

    public PersonProxy(Person person){
        this.person = person;
    }

    @Override
    public void invoke() {
        log.info("代理類統一開始處理");
        person.invoke();
        log.info("代理類統一結束處理");
    }

    public static void main(String[] args) {
        Student s = new Student();
        PersonProxy personProxy = new PersonProxy(s);
        personProxy.invoke();
    }
}

2.1動態代理實現之jdk動態代理

  1. 代理類需要實現InvocationHandler接口
  2. 重寫invoke 方法.通過反射機制調用方法method.invoke(object,args) object-被代理的對象 args-參數
  3. 代理類必須有個屬性對象Object-通過代理類的構造函數傳參進行設值
  4. Proxy.newProxyInstance(loader,clazz,testInvocationHandler)
    loader -類加載器
    clazz - 獲取代理類實現的所有接口
    testInvocationHandler- 委託的代理類
@Slf4j
public class TestInvocationHandler implements InvocationHandler{

    private Object object;

    public TestInvocationHandler(Object o){
        this.object = o;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log.info("類名-{},方法名-{},參數-{}",proxy.getClass().getName(),method.getName(), JSONArray.toJSONString(args));
        // 調用方法、反射機制調用
        Object o = method.invoke(object,args);
        return o;
    }

    public static void main(String[] args) {
        // 創建代理類
        Student s = new Student();
        // 獲取類加載器
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        // 獲取被代理類實現的所有接口
        Class<?>[] clazz = s.getClass().getInterfaces();
        // 創建需要委託的代理類
        TestInvocationHandler testInvocationHandler = new TestInvocationHandler(s);
        // 生成代理類
        Person proxy = (Person) Proxy.newProxyInstance(loader,clazz,testInvocationHandler);
        // 通過代理類調用
        proxy.invoke();

    }
}

2.2動態代理實現之cglib代理

定義對象MyAspect
public class MyAspect {
    public void before(){
        System.out.println("切面-before");
    }
    public void around(){
        System.out.println("切面-around");
    }

    public void after(){
        System.out.println("切面-after");
    }

}
  1. new enhancer 對象
  2. enhancer.setSuperclass(student.getClass())
  3. 設置回調函數 new MethodInterceptor 方法攔截器
  4. 創建代理類 enhancer.create()
public class TestCglibFactory {


    public static void main(String[] args) {
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Volumes/zhengStanC");
        // 目標類
        final Student student = new Student();
        // 切面類
        final MyAspect myAspect = new MyAspect();
        // 代理類 採用cglib
        // 1.1 核心類,new enhancer 對象
        Enhancer enhancer = new Enhancer();
        // 1.2確認父類
        enhancer.setSuperclass(student.getClass());
        // 1.3 設置回調函數 new MethodInterceptor 方法攔截器
        // 參數 目標對象,方法,參數、代理方法
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                // 切面前
                myAspect.before();
                // 執行目標方法
                Object obj =  methodProxy.invokeSuper(proxy,args);
                // 切面後
                myAspect.after();
                return obj;
            }
        });
       // 1.4 創建代理類
        Student proxService = (Student) enhancer.create();
        proxService.invoke();
    }
}

總結

靜態代理
只能代理某個特定的對象,擴展性不好,如果有多個對象都需要創建對應的代理類
動態代理之jdk代理
只能實現代理實現接口的被代理類,如果是被代理類是實現類,是不能夠通過jdk代理實現(Proxy.newProxyInstance 裏的參數class-獲取的是被代理類所有實現接口的類)
那對於代理實現類需要怎麼處理?這時就可以通過cglib代理來實現。
cglib代理
通過繼承的方式來實現的,委託代理會爲每個被代理類創建一個新的類,並且繼承該父類,進而實現代理增強。

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