SpringAOP之動態代理

要學習SpringAOP,那就需要學習一下代理模式,因爲AOP的底層機制就是動態代理;因此我們來了解一下什麼是動態代理…
動態代理與靜態代理
這裏我們使用房東出租房,中介代理租房,和我們去租房來解釋動態代理和靜態代理的異同

靜態代理

  • 靜態代理,因爲之前的博客中有講到靜態代理的例子,這裏就不大費篇幅了。
  • 首先,房東想要出租房子,但又不想自己去宣傳,然後等人來看房,介紹,這樣太浪費自己的時間,所以想把租房這件事讓其他人來代理,於是交給了中介,而我們就直接找中介租房…
  • 房東想要出租房子,這是一個需要代理的事件,可以封裝爲一個接口,然後創建一個真實對象來對外透露一個消息,我要出租房子,中介想代理這個租房來賺錢,因此實現這個接口,並在自己的類中添加了一些功能,例如:給你介紹房子,帶你去看房子,等到我們的時候,直接找中介,中介手中有房源,他帶我們看房子,然後租房子給我們,賺取中介費…

接口:

//租房的接口:抽象
public interface Rent {
    //租房
    void rent();
}

真實對象:

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

中介:

package com.MLXH.staticproxy;
//房屋中介--代理
public class Proxy implements Rent {
    //房東
    private Host host;
    public void setHost(Host host) {
        this.host = host;
    }
    public void rent() {
        lookHouse();
        host.rent();
        fare();
    }
    private void lookHouse(){
        System.out.println("中介帶你看房");
    }
    private void fare(){
        System.out.println("收取中介費");
    }
}

我:

public class You {
    public static void main(String[] args) {
        Host host = new Host();
        Proxy proxy = new Proxy();
        proxy.setHost(host);
        proxy.rent();
    }
}

靜態代理的好處:

  • 可以使真實角色更加純粹,不用去關注一些其他的事情;
  • 公共的業務由代理來完成,實現業務的分工;
  • 公共業務的要擴展的話,可以更加集中和方便;

缺點:

  • 假如現在想要出租房子的房東特別多,那中介要代理,一個房子一個類,類也會隨之增加,使得工作量變大,效率會降低!

我們想需要一種能夠有靜態代理的全部好處,但是又不存在這種缺點的東西。

動態代理

動態代理和靜態代理的角色都是一樣的;靜態代理模式的代理類是我們提前寫好的,動態代理的類是動態生成的

動態代理大概分兩類:

  • 基於接口實現:JDK

  • 基於類實現:cglib

當今用的比較多的是JAVAssist來生成動態代理

瞭解動態代理之前,需要用到下面兩個類:

  • InvocationHandler
  • Proxy

InvocationHandler是由代理實例的調用處理程序實現的接口

invoke(Object proxy, 方法 method, Object[] args)處理代理實例上的方法調用並返回結果。
Proxy提供了創建動態代理類和實例的靜態方法,它也是由這些方法創建的所有動態代理類的超類。**
newProxyInstance(ClassLoader loader, 類<?>[] interfaces, InvocationHandler h)返回指定接口的代理類的實例,該接口將方法調用分派給指定的調用處理程序。
抽象角色:

//租房的接口:抽象
public interface Rent {
    //租房
    void rent();
}

真實角色:

//這個房子要出租
public class Host implements Rent {

    //出租
    public void rent(){
        System.out.println("房東要出租房子");
    }

}

動態代理類生成的接口對象

package com.MLXH.dynamicproxy;

import com.MLXH.staticproxy.Rent;

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

public class InvocationHandlerProxy implements InvocationHandler {

    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }
    //動態生成代理類
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                rent.getClass().getInterfaces(),
                this);
    }
    //proxy:代理類
    //method :代理類的調用處理程序的方法 的對象
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        lookHouse();
        Object result = method.invoke(rent, args);
        zhongJieFei();
        return result;
    }
    private void lookHouse(){
        System.out.println("中介帶看房子");
    }
    private void zhongJieFei(){
        System.out.println("收中介費");
    }
}

測試:

public static void main(String[] args) {

    Host host = new Host();
    InvocationHandlerProxy ihp = new InvocationHandlerProxy();
    ihp.setRent(host);
    Rent proxy = (Rent) ihp.getProxy(); 
    proxy.rent();
}

總結:

  • 一個動態代理,一般代理一類的業務,這裏將代理類寫成了租房子類,可以寫成
   private Object target;
   
   public void setTarget(Object target) {
       this.target = target;
   }

動態代理的好處:

  • 可以使真實角色更加純粹,不用去關注一些公共的事情;
  • 公共的業務由代理來完成,實現業務的分工;
  • 公共業務的要擴展的話,可以更加集中和方便;
  • 一個動態代理,一般代理一類的業務,一個動態代理可以代理多個類,代理接口;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章