如果是通过反射技术调用的方法不能拦截到,否则就可以被拦截
@Aspect
@Component
public class Interceptor {
@Pointcut("execution(org.apache.struts.action.ActionForward cn.itcast.web.action..*.*(org.apache.struts.action.ActionMapping,org.apache.struts.action.ActionMapping,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse))")
private void actionMethod(){
}
@Around("actionMethod()")
public Object intercept(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("被拦截到的方法为:"+ pjp.getSignature().getName());
return pjp.proceed();//执行被拦截的方法
}
}
我们可以这样测试,有没有拦截到我们要执行的方法。
测试结果:execute方法可以被拦截,自定义方法无法拦截。如果继承的是action,可以被拦截到,如果继承的是dispatchAction,不能被拦截到
原因:简单说,如果是通过反射技术调用的方法不能拦截到,否则就可以被拦截。
那么为什么反射技术就不能被拦截到?
之所以我们在执行action执行,他能够被拦截,执行之前输出一句话,客户端从spring里面获得action bean是一个代理对象,代理对象中的方法内部呢:才会调用目标对象的方法,他会在执行代理对象之前呢,先执行输出方法,再执行目标方法,那么我们这样就在执行之前输出了这句话。
DispatchAction 继承 BaseAction ,BaseAction 继承 Action ,最终还是继承的Action,那么我们请求交给DispatchAction 执行时,他还是要执行execute方法,我们的DispatchAction对execute方法做了些手脚,重写了这个方法,他会获得配置文件里面的方法名称parameter,这个执行获取方法会通过反射技术获得method里面的方法。他里面没有接口,如果这个action没有接口,就会采用CGlib重写父类非final方法,
public class DepartmentManageAction extends DispatchAction {
@Resource DepartmentService departmentService;
/**
* 部门添加界面
*/
@Permission(module="department",privilege="insert")
public ActionForward addDepartmentUI(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
DepartmentForm formbean = (DepartmentForm)form;
return mapping.findForward("add");
}
Public class Proxy98 extends DepartmentManageAction{
Private Object target;//目标对象
public ActionForward addDepartmentUI(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
他会调用我们定义的那个通知里面的环绕通知
Return Interceptor。Intercept(pjp){
System.out.println("被拦截到的方法为:"+ pjp.getSignature().getName());
return pjp.proceed();//执行被拦截的方法
判断后面还有没有要执行的切面,没有就会执行
Targer。EditDepartmentmentUi;
我们这样开来,他应该回输出啊,会执行我们定义的输出方法啊,但是你要记住我们无乱使用的是action还是DispatchAction都回先执行execute方法。Spring不会为代理对象重写的父类方法加入通知,他只会调用目标对象的execute方法。
}
}
}
总结:为什么DispatchAction不可以
我们环绕通知切面编程原理,如果要拦截的对象没有实现接口,那么就会对他的内部方法也就目标对象生成代理对象(也就是加入通知),但是我们他不会对被拦截的类的父类方法加入通知,而我们的DispatchAction方法最终还是集成的Action方法,所以会先执行execute方法,execute方法所以不会加入通知,只会直接执行目标对象execute方法,而我们DispatchAction方法重写了execute方法,execute内部会通过invoke反射调用我们的目标方法,也就是上面的addDepartmentUI,我们目标对象addDepartmentUI方法内部本身并没有我们单独加上的处理(比如上面的输出),也就是说真实的执行过程,压根就没调用我们的代理对象,而是直接走的没有加入通知的execute方法。