java基礎——靜態代理和動態代理

java代理模式有靜態代理和動態代理兩種實現方式

一、靜態代理

代理模式可以在不修改被代理對象的基礎上,通過擴展代理類,進行一些功能的附加與增強。代理類和被代理類應該共同實現一個接口,或者是共同繼承某個類。

  優點:

    可以在不修改目標對象的前提下擴展目標對象的功能。
  缺點:
    冗餘:由於代理對象要實現與目標對象一致的接口,會產生過多的代理類。
    不易維護:一旦接口增加方法,目標對象與代理對象都要進行修改。

 

  **靜態代理的特點**

    1、目標角色固定

    2、在應用程序執行前就得到目標角色

    3、代理對象會增強目標對象的行爲

    4、有可能存在多個代理 引起"類爆炸"(缺點)

 

二、動態代理

  動態代理利用了 JDK API,動態地在內存中構建代理對象,從而實現對目標對象的代理功能。

  動態代理又被稱爲 JDK 代理或接口代理。靜態代理與動態代理的區別主要在:

    1、靜態代理在編譯時就已經實現,編譯完成後代理類是一個實際的 class 文件
    2、動態代理是在運行時動態生成的,即編譯完成後沒有實際的 class 文件,而是在運行時動態生成類字節碼,並加載到 JVM 中
  注意:動態代理對象不需要實現接口,但是要求目標對象必須實現接口,否則不能使用動態代理。

  JDK 中生成代理對象主要涉及兩個類,第一個類爲 java.lang.reflect.Proxy,通過靜態方法 newProxyInstance 生成代理對象,第二個爲 java.lang.reflect.InvocationHandler 接口,通過 invoke 方法對業務進行增強

  **動態代理的特點**

    1、目標對象不固定

    2、在應用程序執行時動態創建目標對象

    3、代理對象會增強目標對象的行爲

三、代碼實例

  1、創建一個person接口,這個接口就是租客和中介的公共接口,這個接口有一個rentHouse()方法。

public interface Person {

    //租房
    public void rentHouse();
}

 

  2、創建租客Renter類,實現上述接口

public class Renter implements Person{

    @Override
    public void rentHouse() {
        System.out.println("租客租房成功!");
        
    }

}

  3、靜態代理

    1)創建中介類RenterProxy,同樣實現Person接口,但是還另外持有一個租客類對象
public class RenterProxy implements Person{
    private Person renter;
    public RenterProxy(Person renter){
        this.renter = renter;
    }
    @Override
    public void rentHouse() {
        System.out.println("中介找房東租房,轉租給租客!");
        renter.rentHouse();
        System.out.println("中介給租客鑰匙,租客入住!");
        
    }

}

    2)測試

public class StaticProxyTest {

    public static void main(String[] args) {
        Person renter = new Renter();
        RenterProxy proxy = new RenterProxy(renter);
        proxy.rentHouse();
    }

}

運行結果:
中介找房東租房,轉租給租客!
租客租房成功!
中介給租客鑰匙,租客入住!

   4、動態代理

    1)創建RenterInvocationHandler類,這個類實現了InvocationHandler接口,並持有一個被代理類的對象,InvocationHandler中有一個invoke方法,所有執行代理對象的方法都會被替換成執行invoke方法。然後通過反射在invoke方法中執行代理類的方法。在代理過程中,在執行代理類的方法前或者後可以執行自己的操作,這就是spring aop的主要原理。

public class RenterInvocationHandler<T> implements InvocationHandler{
    //被代理類的對象
    private T target;
    
    public RenterInvocationHandler(T target){
        this.target = target;
    }

    /**
     * proxy:代表動態代理對象
     * method:代表正在執行的方法
     * args:代表調用目標方法時傳入的實參
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        //代理過程中插入其他操作
        System.out.println("租客和中介交流");
        Object result = method.invoke(target, args);
        return result;
    }

}

    2)測試

public class ProxyTest {

    public static void main(String[] args) {

        //創建被代理的實例對象
        Person renter = new Renter();
        //創建InvocationHandler對象
        InvocationHandler renterHandler = new RenterInvocationHandler<Person>(renter);
        
        
        //創建代理對象,代理對象的每個執行方法都會替換執行Invocation中的invoke方法
        Person renterProxy = (Person)Proxy.newProxyInstance(Person.class.getClassLoader(),new Class<?>[]{Person.class}, renterHandler);
        renterProxy.rentHouse();
        
        //也可以使用下面的方式創建代理類對象,Proxy.newProxyInstance其實就是對下面代碼的封裝
        /*try {
            //使用Proxy類的getProxyClass靜態方法生成一個動態代理類renterProxy 
            Class<?> renterProxyClass = Proxy.getProxyClass(Person.class.getClassLoader(), new Class<?>[]{Person.class});
            //獲取代理類renterProxy的構造器,參數爲InvocationHandler
            Constructor<?> constructor = renterProxyClass.getConstructor(InvocationHandler.class);
            //使用構造器創建一個代理類實例對象
            Person renterProxy = (Person)constructor.newInstance(renterHandler);
            renterProxy.rentHouse();
            //
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }*/
    }

}

執行結果:
租客和中介交流
租客租房成功!

 

 

 

參考:

https://blog.csdn.net/zjshuster/article/details/126439883

https://blog.csdn.net/qq_34609889/article/details/85317582

https://blog.csdn.net/longzorg_cn/article/details/129115728 

https://blog.csdn.net/m0_67499084/article/details/124810718 

一個person接口,這個接口就是租客和中介的公共接口,這個接口有一個rentHouse()方法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章