動態代理

tags: Spring-代理模式
  • 動態代理和靜態代理角色一樣
  • 動態代理的代理類是動態生成的,不是我們直接寫
  • 動態代理分為兩大類:基於接口的動態代理、基於類的動態代理
    基於接口JDK動態代理
    基於類cglib
    java字節碼實現:javassist

需要了解兩個類:Proxy 代理、InvocationHandler 調用處理程序

InvocationHandler

nvocationHandler接口是proxy代理實例的調用處理程序實現的一個接口,每一個proxy代理實例都有一個關聯的調用處理程序;在代理實例調用方法時,方法調用被編碼分派到調用處理程序的invoke方法

實現操作

1.接口

//租房 public interface Rent { public void rent(); }

2.真實對象

//房東
public class Host implements Rent {

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

3.自動生成代理類

//我們會用這個類,自動生成代理類 public class ProxyInvocationHandler implements InvocationHandler { //被代理的接口 private Rent rent; public void setRent(Rent rent){ this.rent = rent; } //生成得到代理類 public Object getProxy(){ //如果操作Proxy.newProxyInstance()傳回的代理物件,會呼叫invoke方法 return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this); } //處理代理實例,並返回結果 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //動態代理的本質,就是使用反射機制實現 //用反射(invoke),執行接口下的方法,args 參數 seeHouse(); Object result = method.invoke(rent, args); fare(); return result; } 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(); //代理角色:現在沒有 ProxyInvocationHandler pih = new ProxyInvocationHandler(); //通過調用程序處理角色來處理我們要調用的接口對象 pih.setRent(host); Rent proxy = (Rent) pih.getProxy();//這裡的proxy就是動態實現生成的,我們並沒有寫 proxy.rent(); } }

通用版

//我們會用這個類,自動生成代理類 public class ProxyInvocationHandler implements InvocationHandler { //被代理的接口(真實對象) private Object target; public void setTarget(Object target) { this.target = target; } //生成得到代理類 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } //處理代理實例,並返回結果 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //利用反射 log(method.getName()); Object result = method.invoke(target, args); return result; } public void log(String msg){ System.out.println("執行了" + msg + "方法"); } }

動態代理的好處

  • 可以使真實角色的操作更加純粹,不用去關注一些公共的業務
  • 公共業務也就交給代理角色,實現了業務的分工
  • 公共業務發生擴展的時候,方便集中管理
  • 一個動態代理類代理的是一個接口,一般就是對應一類業務
  • 一個動態代理類可以代理多個類,只要是實現同一個接口即可