設(shè)計模式_代理_動態(tài)代理

1.代理模式概述

1.1什么是代理模式

ProxyPattern(即:代理模式)23種常用的面向?qū)ο筌浖脑O(shè)計模式之一。
代理模式的定義:為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標(biāo)對象之間起到中介的作用。
作用:增強一個類中的某個方法.對程序進行擴展. Spring框架中AOP.

1.2動態(tài)代理介紹

動態(tài)代理它可以直接給某一個目標(biāo)(被代理 對象)對象(實現(xiàn)了某個或者某些接口)生成一個代理對象,而不需要代理類存在。
動態(tài)代理與代理模式原理是一樣的,只是它沒有具體的代理類,直接通過反射生成了一個代理對象。

動態(tài)代理的分類

  • jdk提供一個Proxy類可以直接給實現(xiàn)接口類的對象直接生成代理對象
  • spring中動態(tài)代理:cglib

2.jdk中的動態(tài)代理的使用

2.1API介紹

Java.lang.reflect.Proxy類可以直接生成一個代理對象

Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)生成一個代理對象
參數(shù)1:ClassLoader loader 代理對象的類加載器 一般使用被代理對象的類加載器
參數(shù)2:Class<?>[] interfaces 代理對象的要實現(xiàn)的接口 一般使用的被代理對象實現(xiàn)的接口
參數(shù)3:InvocationHandler h (接口)執(zhí)行處理類

InvocationHandler中的invoke(Object proxy, Method method, Object[] args)方法:調(diào)用代理類的任何方法,此方法都會執(zhí)行
-參數(shù)3.1Object proxy:代理對象(慎用)
-參數(shù)3.2Method method:當(dāng)前執(zhí)行的方法
-參數(shù)3.3Object[] args:當(dāng)前執(zhí)行的方法運行時傳遞過來的參數(shù)
返回值:當(dāng)前方法執(zhí)行的返回值

2.2代碼實現(xiàn)

/**  規(guī)范接口
 * Created by liangtong.
 */
public interface Actor {
    /**
     * 唱歌
     * @return
     */
    public String sing();

    /**
     * 跳舞
     * @return
     */
    public String dance();
}
/** 目標(biāo)類:劉德華類,需要被代理的類。
 * Created by liangtong.
 */
public class Liudehua implements Actor {
    @Override
    public String sing() {
        return "華仔唱歌";
    }

    @Override
    public String dance() {
        return "華仔跳舞";
    }
}
public class TestProxy {
    /*
    1.工具類 Proxy.newProxyInstance(); 運行時創(chuàng)建代理類
        Object object = Proxy.newProxyInstance()
    2. 參數(shù)
        參數(shù)1:類加載器,負(fù)責(zé)將新創(chuàng)建的類添加到內(nèi)存中。
        參數(shù)2:確定需要實現(xiàn)接口們,java可以多實現(xiàn),需要同一個數(shù)組。
        參數(shù)3:處理類,接口InvocationHandler
            //調(diào)用代理類的每一個方法,都將執(zhí)行處理類的invoke方法。
            參數(shù)a) proxy 代理類,一般沒用
            參數(shù)b) method 當(dāng)前執(zhí)行的方法
            參數(shù)c) args 方法的實際參數(shù)
 */
    @Test
    public void testDemo2(){
        //目標(biāo)類
        Actor target = new Liudehua();
        //1 類加載  代理對象的類加載器  責(zé)將新創(chuàng)建的類添加到內(nèi)存中
        ClassLoader classLoader = TestProxy.class.getClassLoader();
        //2 接口   代理對象的要實現(xiàn)的接口
        Class[] interfaces = {Actor.class};
        //3 處理類,接口InvocationHandler
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("代理收錢之后!");
                return method.invoke(target,args);
            }
        };
        //創(chuàng)建目標(biāo)類
        Actor actor = (Actor) Proxy.newProxyInstance(classLoader,interfaces,invocationHandler);
        //調(diào)用方法并打印
        System.out.println(actor.sing());
        System.out.println(actor.dance());
    }
}

2.4代碼實現(xiàn)(加強)

public interface Person {

    void eat();

    void sleep(Integer hours);
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Wash {

}
public class Student implements Person {
    @Override
    public void eat() {
        System.out.println("學(xué)生在吃飯");
    }

    @Wash
    @Override
    public void sleep(Integer hours) {
        System.out.println("學(xué)生在睡覺,睡了" + hours + "個小時");
    }
}
public class PersonFactory {

    public static Person getPerson() {
        //增強
        Student student = new Student();
        ClassLoader classLoader = student.getClass().getClassLoader();
        Class<?>[] interfaces = student.getClass().getInterfaces();

        Person obj = (Person) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {

            /**
             *
             * @param proxy 代理對象
             * @param method 代理方法
             * @param args 調(diào)用代理方法時傳遞的參數(shù)
             * @return
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                Class<?>[] argClass = null;
                if (args != null) {
                    argClass = new Class[args.length];
                    //獲取所有參數(shù)的類型
                    for (int i = 0; i < args.length; i++) {
                        argClass[i] = args[i].getClass();
                    }
                }

                //獲取方法名
                String methodName = method.getName();

                //獲取原始的方法
                Method originMethod = student.getClass().getMethod(methodName, argClass);
                System.out.println(originMethod);

                //判斷方法是否需要增強
                if (originMethod.isAnnotationPresent(Wash.class)) {
                    System.out.println("之前洗漱");

                    Object obj = method.invoke(student, args);

                    System.out.println("之后洗漱");
                    return obj;
                }

                return method.invoke(student, args);
            }
        });
        return obj;
    }
}
public class StudentTest {
    @Test
    public void test() {
        Person person = PersonFactory.getPerson();
        person.eat();
        person.sleep(8);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容