攔截器模式應用非常廣泛,適用場景一般在框架代碼中的固定業務邏輯,這部分邏輯通常不會變化,比如:服務調用的攔截處理,攔截服務的參數,參數國際化處理,攔截服務的異常,記錄服務的調用結果等等。
之所以要講這個,是因爲後面講SpringAOP的時候會參考到!
攔截器模式有三個重要的元素:調度器,攔截器,業務邏輯,只要充分理解這三個元素,攔截器模式就很簡單了。
-
調度器
一個業務邏輯可以有N個攔截器,這些攔截器是怎麼運行的,自然是需要有一個調度器從中調度。
-
攔截器
攔截器就只是負責攔截業務代碼,在業務代碼前後做一些操作,至於攔截器和業務代碼的關係,攔截器不會直接調用業務代碼,因爲會耦合,攔截器在處理完自己的邏輯,會通知調度器,由調度器負責後續的操作,是繼續攔截,還是調用業務邏輯。
-
業務邏輯
業務代碼這一塊沒啥好說的。
舉個代碼最少的例子,業務場景:服務調用,攔截服務調用記錄日誌,以及做異常處理。
既然有兩個攔截器,自然要有一個攔截器接口。
1、攔截器接口
public interface Interceptor {
void before(Invocation invocation);
String intercept(Invocation invocation);
void after(Invocation invocation);
}
2、日誌攔截器
public class LogInterceptor implements Interceptor {
@Override
public void before(Invocation invocation) {
System.out.println("LogInterceptor before...");
}
@Override
public String intercept(Invocation invocation) {
this.before(invocation);
invocation.invoke();
this.after(invocation);
return null;
}
@Override
public void after(Invocation invocation) {
System.out.println("LogInterceptor after...");
}
}
3,異常攔截器
public class ExceptionInterceptor implements Interceptor {
@Override
public void before(Invocation invocation) {
System.out.println("ExceptionInterceptor before...");
}
@Override
public String intercept(Invocation invocation) {
this.before(invocation);
// 實際代碼應該是try catch,在catch中做事情
invocation.invoke();
this.after(invocation);
return null;
}
@Override
public void after(Invocation invocation) {
System.out.println("ExceptionInterceptor after...");
}
}
4、調度器代碼
public class Invocation {
int index = 0;
// 調度器管理業務
private BusinessService bs;
// 調度器管理攔截器List
private List<Interceptor> interceptions = new ArrayList<Interceptor>();
public Invocation() {
interceptions.add(new LogInterceptor());
interceptions.add(new ExceptionInterceptor());
}
public void invoke() {
if (index == interceptions.size()) {
bs.perform();
}
else {
Interceptor interceptor = interceptions.get(index);
index++;
interceptor.intercept(this); // 傳this(調度器)用於回調
}
}
public void setBusinessService(BusinessService bs) {
this.bs = bs;
}
}
5、業務代碼
public class BusinessService {
public void perform() {
System.out.println("服務調用。。。");
}
}
6,測試方法
public static void main(String[] args) {
Invocation invocation = new Invocation(); // 直接在構造裏面就把兩個攔截器加上
invocation.setBusinessService(new BusinessService()); // 加上業務邏輯
invocation.invoke();
}
輸出結果:
LogInterceptor before...
ExceptionInterceptor before...
服務調用。。。
ExceptionInterceptor after...
LogInterceptor after...