要學習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;
}
動態代理的好處:
- 可以使真實角色更加純粹,不用去關注一些公共的事情;
- 公共的業務由代理來完成,實現業務的分工;
- 公共業務的要擴展的話,可以更加集中和方便;
- 一個動態代理,一般代理一類的業務,一個動態代理可以代理多個類,代理接口;