我们大家都知道,Interceptor的接口定义没有什么特别的地方,除了init和destory方法以外,intercept方法是实现整个拦截器机制的核心方法。而它所依赖的参数ActionInvocation则是著名的Action调度者。我们再来看看一个典型的Interceptor的抽象实现类: public abstract class AroundInterceptor extends AbstractInterceptor { //com.opensymphony.xwork2.interceptor.AbstractInterceptor#int//ercept(com.opensymphony.xwork2.ActionInvocation) @Override
public String intercept(ActionInvocation invocation) throws Exception { String result = null; before(invocation); // 调用下一个拦截器,如果拦截器不存在,则执行Action
result = invocation.invoke();
after(invocation, result);
return result; }
public abstract void before(ActionInvocation invocation) throws Exception; public abstract void after(ActionInvocation invocation, String resultCode) throws Exception; } 在这个实现类中,实际上已经实现了最简单的拦截器的雏形。这里需要指出的是一个很重要的方法invocation.invoke()。这是ActionInvocation中的方法,而ActionInvocation是Action调度者,所以这个方法具备以下4层含义:
public String intercept(ActionInvocation invocation) throws Exception { invocation.addPreResultListener(new PreResultListener() { public void beforeResult(ActionInvocation invocation, StringresultCode) { /********** 要添加的代码 ***********/ } }); String returnString = invocation.invoke(); return returnString; } 注意:在addPreResultListener里的异常,不会被Struts的框架捕获 由此,我们就可以通过invocation.invoke()作为Action代码真正的拦截点,从而实现AOP。 三.源码解析 下面我们通过查看源码来看看Struts2是如何保证拦截器、Action与Result三者之间的执行顺序的。之前我曾经提到,ActionInvocation是Struts2中的调度器,所以事实上,这些代码的调度执行,是在ActionInvocation的实现类中完成的,这里,我抽取了DefaultActionInvocation中的invoke()方法,它将向我们展示一切。 // * @throws ConfigurationException If no result can be //found with the returned code public String invoke() throws Exception {
String profileKey = "invoke: ";
try {
UtilTimerStack.push(profileKey); if (executed) { throw new IllegalStateException("Action has already executed");
} // 依次调用拦截器堆栈中的拦截器代码执行 if (interceptors.hasNext()) {
final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();