Spring aop: 通过注解实现对controller的aop,出现的问题
Posted ajjiangxin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring aop: 通过注解实现对controller的aop,出现的问题相关的知识,希望对你有一定的参考价值。
前提1:web.xml中:
<servlet> <servlet-name>Spring-mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/DispatcherServlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Spring-mvc</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping>
前提2:DispatcherServlet.xml中(另外就是几个interceptor)
前提3: 后文描述的情况,在<aop:aspectj-autoproxy proxy-target-class="true"/>与<aop:aspectj-autoproxy proxy-target-class="false"/>两种前提下,结果毫无差别。
<context:component-scan base-package="com"></context:component-scan> <mvc:annotation-driven /> <aop:aspectj-autoproxy />
前提4:controller为com.BaseController,通过<context:component-scan base-package="com"></context:component-scan>生成
@Component
@Aspect
public class aopDefault {
private long beginTime;
@Pointcut("execution(* org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(..))")
private void aspect(){}//定义一个切入点
@Pointcut("execution(* com.BaseController.*(..))")
private void _aspect(){}//定义一个切入点
@Before("execution(* com.BaseController.*(..))")//定义前置通知
public void doBefore(){
beginTime = System.currentTimeMillis();
System.out.println("doBefore");
}
@AfterReturning("execution(* com.BaseController.*(..))")//定义后置通知
public void doAfter(JoinPoint joinpoint){
String className = joinpoint.getTarget().getClass().getName();
String method = joinpoint.getSignature().getName();
long endTime = System.currentTimeMillis();
long duration= endTime-beginTime;
System.out.println("doAfter");
System.out.println("Method: "+className+"."+method);
System.out.println("Elapsed time : "+duration + "ms");
System.out.println("");
}
//doAround注解方法1
@Around("aspect()")
public void doAround(){
System.out.println("doAround_1");
}
//doAround注解方法2
@Around("_aspect()")
public void _doAround(){
System.out.println("doAround_2");
}
//doAround注解方法3
@Around("execution(* org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(..))")
public void _doAround_(){
System.out.println("doAround_3");
}
}
结果:
控制台(显然,“doAround注解方法1” 和 “doAround注解方法3” 完全不起作用,而Before,AfterReturning都OK,说明
("execution(* com.BaseController.*(..))")
这种写法用在定义@pointcut是无效的,但直接写在方法里是有效的,而
("execution(* org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(..))")
这玩意儿,反正在我这是死活没有一点儿用,再说一遍proxy-target-class="true"还是"false"都没用):
doAround_2
doAfter
Method: com.BaseController.login
Elapsed time : 1466612786129ms
页面部分结果(结果为error,就算将“返回值json”这一条件去除,也得不到任何返回值):
ajax.js:51 200
ajax.js:52 4
ajax.js:53 parsererror
ajax代码为
$.ajax({
url:"login.do",
type:"post",
dataType:"json",
data:{userName:username, userPwd:pwd},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log(XMLHttpRequest.status);
console.log(XMLHttpRequest.readyState);
console.log(textStatus);
},
success: function(json){
...
}
});
但是!!!一旦把“doAround注解方法2”给注释掉,即不使用 ("execution(* com.BaseController.*(..))") 形式的@pointcut时,控制台输出和页面的操作反应就全部正常了(这里interceptor完全无关),完全正常。
综上!!!,我从各个帖子处看过来的种种通过注释对controller实现aop的方法,至少在我实践来看都不太靠谱(还包括expression里是...org.springframework.stereotype.Controller...等,这里就不放例子了),靠谱的只有一种方法:
不使用pointcut, 而直接在before,afterreturning,doaround等方法后写类似("execution(* com.BaseController.*(..))")的形式
btw,抱歉写的可能很让人头晕,水平有限。
这是参考的帖子:
http://itindex.net/detail/50710-springaop-controller-service/
http://yjian84.iteye.com/blog/1920787
http://phoenixfu.iteye.com/blog/2037598
http://www.oschina.net/question/222929_124314?fromerr=BICW0JoJ
http://usherlight.iteye.com/blog/1306111
以上是关于Spring aop: 通过注解实现对controller的aop,出现的问题的主要内容,如果未能解决你的问题,请参考以下文章