首頁  >  文章  >  Java  >  Java中動態代理程式和靜態代理程式的範例分析

Java中動態代理程式和靜態代理程式的範例分析

WBOY
WBOY轉載
2023-05-05 21:37:081537瀏覽

    0、代理模式

    為什麼要學習代理模式?這是SpringAOP的底層【SpringAOP和SpringMVC】

    代理模式的分類:

    • # 代理程式

    • ##動態代理

    • 1、靜態代理

    • 靜態代理程式中,我們對目標物件的每個方法的增強都是手動完成的(後面會具體示範程式碼_),非常不靈活(例如介面一旦新增加方法,目標物件和代理物件都要進行修改)且麻煩(_需要對每個目標類別都單獨寫一個代理類別
    • )。實際應用場景非常非常少,日常開發幾乎看不到使用靜態代理的場景。

    • 角色分析:

    抽象角色:一般會使用介面或抽象類別來解決

    真實角色:被代理的角色

    代理角色:代理真實角色,代理真實角色後,我們一般會做一些附屬操作

    客戶:訪問代理對象的人!
    • 程式碼步驟:
    • 1、介面
    • public interface Rent {
          public void rent();
      }
    • 2、真實角色

      //房东
      public class Host implements Rent {
          public void rent() {
              System.out.println("房东要租房子");
          }
      }

      3、代理角色
    • public class Proxy implements Rent{
          private Host host;
          public Proxy() {
          }
          public Proxy(Host host) {
              this.host = host;
          }
          public void rent(){
              seeHouse();
              host.rent();
              fare();
          }
          //看房
          public void seeHouse(){
              System.out.println("中介带你看房");
          }
          //收中介费
          public void fare(){
              System.out.println("中介收费");
          }
      }
    4、客服端存取代理角色

    public class Client {
        public static void main(String[] args) {
            Host host = new Host();
            //代理,代理角色一般会有附属操作!
            Proxy proxy = new Proxy(host);
            proxy.rent();
        }
    }
    #代理模式的好處:

    ##可以讓真實角色的操作更加純粹!不用去關註一些公共的業務

    公共也交給代理角色!實現業務的分工! Java中動態代理程式和靜態代理程式的範例分析

    公共業務發生擴充的時候,方便集中管理!
    • 缺點:
    • 一個真實角色會產生一個代理角色;從JVM角度來看,靜態代理在編譯時就會介面、實作類別、代理類別這些都變成了一個個實際的class檔案。
    • 2、加深理解

      AOP,的底層代理模式
      • #3、動態代理
      • 動態代理程式和靜態代理角色一樣
      • 動態代理程式的代理程式類別是動態產生的,不是我們直接寫好的!

    動態代理分為兩大類:基於介面的動態代理,基於類別的動態代理

    ##基於介面— —JDK動態代理

    基於類別:cglib動態代理

    • java字節碼實作:javasist

    • #需要了解兩個類別:Proxy: 代理類,InvocationHandler : 呼叫處理程序

    從JVM 角度來說,動態代理是在運行時動態產生類字節碼,並載入到JVM 中的。

    //Proxy是生成动态代理类,提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
    //InvocationHandler-- invoke 调用处理程序并返回接口, 是由代理实例的调用处理程序实现的接口 。
    動態代理程式的好處:

    #可以讓真實角色的操作更加純粹!不用去關係一些公共的業務

    公共也交給代理角色!實作

    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h){
    }
    1.loader

    :類別載入器,用於載入代理物件。 2.interfaces 

    : 被代理類別實作的一些介面;

    3.

    h : 實作了 InvocationHandler

     介面的物件;

    #要實作動態代理的話,也必須實作InvocationHandler

     來自訂處理邏輯。當我們的動態代理物件呼叫一個方法時,這個方法的呼叫就會被轉送到實作

    InvocationHandler

     介面類別的 

    invoke

     方法來呼叫。

    public interface InvocationHandler {
        Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
    }

    1.

    proxy :動態產生的代理類別

    #2.method : 與代理類別物件呼叫的方法相對應#3.

    args : 目前method 方法的參數

    動態代理程式的範例

    1、定義介面

    public interface Rent {
        public void rent();
    }
    2、實作租屋的介面
    public class Host implements Rent {
        @Override
        public void rent() {
            System.out.println("房东要租房");
        }
    }

    3、定義一個JDK動態代理類別

    public class DebugInvocationHandler implements InvocationHandler {
        /**
         * 代理类中的真实对象
         */
        private final Object target;
        public DebugInvocationHandler(Object target){
            this.target = target;
        }
        /**
         * 当你使用代理对象调用方法的时候实际会调用到这个方法
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //调用方法前
            System.out.println("before method" + method.getName());
            Object res = method.invoke(target, args);
            //调用方法后
            System.out.println("after method" + method.getName());
            return res;
        }
    }

    #invoke() 方法: 當我們的動態代理物件呼叫原生方法的時候,最終實際上調用到的是 invoke()

     方法,然後 
    invoke()

     方法取代我們去呼叫了被代理物件的原生方法。

    4、取得代理物件的工廠類別

    public class JdkProxyFactory {
        public static Object getProxy(Object target){
            return Proxy.newProxyInstance(
                    target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(),
                    new DebugInvocationHandler(target)
            );
        }
    }
    ###getProxy()### :主要透過###Proxy.newProxyInstance()###方法取得某個類別的代理對象######5、實際使用###
    public static void main(String[] args) {
            //Rent rent = new Host();
            //Rent rentProxy= (Rent) Proxy.newProxyInstance(rent.getClass().getClassLoader(), rent.getClass().getInterfaces(),new DebugInvocationHandler(rent));
            Rent rentProxy = (Rent)JdkProxyFactory.getProxy(new Host());
            rentProxy.rent();
        }
    #######執行上述代理的輸出###########before methodrent###房東要租房子################## after methodrent######

    以上是Java中動態代理程式和靜態代理程式的範例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    陳述:
    本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除