# 動態代理
###### tags: `Spring-代理模式`
* 動態代理和靜態代理角色一樣
* 動態代理的代理類是動態生成的,不是我們直接寫
* 動態代理分為兩大類:基於接口的動態代理、基於類的動態代理
基於接口--JDK動態代理
基於類--cglib
java字節碼實現:javassist
需要了解兩個類:Proxy 代理、InvocationHandler 調用處理程序
## InvocationHandler
nvocationHandler接口是proxy代理實例的調用處理程序實現的一個接口,每一個proxy代理實例都有一個關聯的調用處理程序;在代理實例調用方法時,方法調用被編碼分派到調用處理程序的invoke方法
### 實現操作
1.接口
```java=
//租房
public interface Rent {
public void rent();
}
```
2.真實對象
```
//房東
public class Host implements Rent {
@Override
public void rent() {
System.out.println("房東要出租房子");
}
}
```
**3.自動生成代理類**
```java=
//我們會用這個類,自動生成代理類
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.客戶端
```java=
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();
}
}
```
### 通用版
```java=
//我們會用這個類,自動生成代理類
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 + "方法");
}
}
```
### 動態代理的好處
* 可以使真實角色的操作更加純粹,不用去關注一些公共的業務
* 公共業務也就交給代理角色,實現了業務的分工
* 公共業務發生擴展的時候,方便集中管理
* 一個動態代理類代理的是一個接口,一般就是對應一類業務
* 一個動態代理類可以代理多個類,只要是實現同一個接口即可