上篇文章中,Filter過濾器中的案例,對請求過來的參數進行敏感詞彙過濾,如果是敏感詞彙就修改成 *** , 然後再放行給對應的Servlet進行處理請求。那麼通過Filter進行了過濾和增強。加入服務端有100個接口,那麼通過一個Filter就可以對所有的接口請求進行過濾和處理,然後再放行給對應的Servlet。示例裏用到了動態代理,下面簡單介紹下。
設計模式:一些通用的解決固定問題的方式 ,這裏介紹 代理模式
概念:
- 真實對象:被代理的對象
- 代理對象:
- 代理模式:代理對象代理真實對象,達到增強真實對象功能的目的
實現方式:
- 靜態代理:有一個類文件描述代理模式
- 動態代理:在內存中形成代理類
實現步驟:
- 代理對象和真實對象實現相同的接口
- 代理對象 = Proxy.newProxyInstance();
- 使用代理對象調用方法。
- 增強方法
增強方式:
- 增強參數列表
- 增強返回值類型
- 增強方法體執行邏輯
示例
定義一個賣電腦的接口
public interface SaleComputer {
public String sale(double money);
public void show();
}
定義真實賣電腦的廠商
/**
* 真實類
*/
public class Lenovo implements SaleComputer {
@Override
public String sale(double money) {
return "花了"+money+"元買了一臺聯想電腦...";
@Override
public void show() {
System.out.println("展示電腦....");
}
}
代理測試
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
//1.創建真實對象
Lenovo lenovo = new Lenovo();
//2.動態代理增強lenovo對象
/*
三個參數:
1. 類加載器:真實對象.getClass().getClassLoader()
2. 接口數組:真實對象.getClass().getInterfaces()
3. 處理器:new InvocationHandler()
*/
SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
/*
代理邏輯編寫的方法:代理對象調用的所有方法都會觸發該方法執行
參數:
1. proxy:代理對象
2. method:代理對象調用的方法,被封裝爲的對象
3. args:代理對象調用的方法時,傳遞的實際參數
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//判斷是否是sale方法
if(method.getName().equals("sale")){
//1.增強參數
double money = (double) args[0];
money = money * 0.85;
System.out.println("專車接你....");
//使用真實對象調用該方法
String obj = (String) method.invoke(lenovo, money);
System.out.println("免費送貨...");
//2.增強返回值
return obj+"送鼠標墊";
}else{
Object obj = method.invoke(lenovo, args);
return obj;
}
}
});
//3.如果調用代理過的方法
String computer = proxy_lenovo.sale(1000);
System.out.println(computer);
proxy_lenovo.show();
//如果調用正常的方法
System.out.println("------");
lenovo.sale(1000);
lenovo.show();
}
}
輸出結果:
專車接你
免費送貨
花了850元買了一臺聯想電腦...送鼠標墊
展示電腦
------
花了1000元買了一臺聯想電腦...
展示電腦
示例中,通過代理,對lenovo 對象的sale方法進行了"增強";
通過Proxy.newProxyInstance 方法生成了一個動態代理的對象,這個對象沒有物理代碼,而是被動態生成在內存中,
當通過返回的proxy_lenovo代理對象執行方法時, InvocationHandler 的invoke方法會被執行,可以獲取到當前被執行的方法是什麼,參數是什麼,然後你可以動態做一些邏輯處理, 比如這裏就通過代理,對sale方法進行數據處理和加了一些邏輯,然後最後相當於修改了返回值,invoke方法的返回值就是sale方法最後的返回值。
通過示例可以看出,對象被代理後,可以自定義對象方法被調用時的參數,邏輯,返回值,也就是對方法進行"增強".