說說對Struts 2攔截器的理解?

理解攔截器

    攔截器可以動態地攔截髮送到指定Action的請求,通過攔截器機制,我們可以在Action執行的前後插入某些代碼。通過這種方式,久可以把多個Action中需要重複指定的代碼提取出來,放在攔截器裏面定義,從而提供更好的代碼重用性。攔截器機制是一種非常靈活的軟件服用方式。

 

攔截器的實現原理

    大部分時候,攔截器方法都是用過代理的方式來調用的。下面以JDK動態代理爲例來介紹如何調用攔截器方法。

    下面是一個簡單的Dog接口,因爲JDK動態代理只能對實現了接口的實例來生成代理,因此必須提供一個Dog接口,該接口代碼非常簡單。

 

1、接口代碼

package cn.cdi.intercepter;

public interface Dog {
 //info方法聲明
 public void info();
 //run方法聲明
 public void run();
}


2、下面提供接口的實現

package cn.cdi.intercepter;

public class DogImpl implements Dog {
 //info方法的實現,僅僅打印一個字符串
 public void info() {
  System.out.println("我是一條狗");
 }
 //run方法的實現,僅僅打印一個字符串
 public void run() {
  System.out.println("我奔跑迅速");
 }
}

 

3、攔截器類

package cn.cdi.intercepter;

public class DogIntercepter {
 //第一個攔截器方法
 public void method1() {
  System.out.println("=====模擬通用方法=====");
 }
 //第二個攔截器方法
 public void method2() {
  System.out.println("=====模擬通用方法=====");
 }
}


4、假如我們需呀上面的info方法執行前後分別調用攔截器裏的方法,系統應該如何實現呢?關鍵定義一個ProxyHandler類。該類需要實現InvocationHandler接口,該接口是JDK反射體系裏的一個接口,他是一個可以動態調用目標對象的方法。

package cn.cdi.intercepter;

import java.lang.reflect.InvocationHandler;

public class ProxyHandler implements InvocationHandler{
 //需被代理的目標對象
 private Object target;
 //創建攔截器實例
 DogIntercepter di = new DogIntercepter();
 //執行代理的目標方法時,該invoke方法會被自動調用
 public Object invoke(Objectproxy,java.lang.reflect.Method method,Object[] args) throwsException {
  Object[] result = null;
  //如果被調用方法的方法名爲info
  if(method.getName().equals("info")){
   //調用攔截器方法1
   di.method1();
   result =(Object[]) method.invoke(target, args);
   //調用攔截器方法2
   di.method2();
  }else {
   result =(Object[]) method.invoke(target, args);
  }
  return result;
 }
 //用於設置傳入目標對象的方法
 public void setTarget(Object o) {
  this.target = o;
 }
}
5、還需要提供一個代理工廠,代理工程的主要作用就是更具目標對象生成一個代理對象:

package cn.cdi.intercepter;

import java.lang.reflect.Proxy;

public class MyProxyFactory {
 public static Object getProxy(Object object){
  //代理的處理類
  ProxyHandler handler = newProxyHandler();
  //把該Dog實例託付給代理操作
  handler.setTarget(object);
  //第一個參數是用來創建動態代理的ClassLoader對象
  //只要該對象能訪問Dog接口即可
  //第二個參數是接口數組,正是代理該接口的數組
  //第三個參數是代理包含的處理實例
  returnProxy.newProxyInstance(DogImpl.class.getClassLoader(),object.getClass().getInterfaces(), handler);
 }
}
代理工程裏有行代碼:

Proxy.newProxyInstance(DogImpl.class.getClassLoader(),object.getClass().getInterfaces(), handler);

    Proxy.newProxyInstance()方法根據接口數組動態創建代理類實例,接口數組通過object.getClass().getInterfaces(),方法獲取,創建代理類是JVM在內存中動態創建,該類實現傳入參數裏接口數組中的全部接口。因此,DynamicProxy要求被代理的必須是接口的實現類,否則無法爲其構造相應的動態實例。

   從上面的介紹可以看出,代理工程負責根據目標對象和對應的攔截器生成新的代理對象,代理對象裏的方法是目標方法和攔截器方法的組合。正是通過這種方式,實現了在目標方法之前或者之後,自動調用攔截器方法。

 

6、運行主程序

package cn.cdi.intercepter;

public class TestDog {
 public static void main(String[] args) {
  //創建一個Dog實例,該實例將被作爲代理的目標對象
  Dog targetObject = newDogImpl();
  Dog dog = null;
  //以目標對象創建代理
  Object proxy =MyProxyFactory.getProxy(targetObject);
  if(proxy instanceof Dog){
   dog = (Dog)proxy;
  }
  //測試代理的方法
  dog.info();
  dog.run();
 }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章