使用@Aspect注解进行aop进行性能监控以及异常记录
1、定义aop类
package com.szwx.springmvc.common.aop;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import com.szwx.springmvc.common.util.PropertiesFactory;
import com.szwx.springmvc.common.util.PropertiesHelper;
import com.szwx.springmvc.common.util.PropertyFiles;
@Component
@Aspect
public class AopLog {
private static Logger log = Logger.getLogger(AopLog.class);
// 定义切入点
@Pointcut("execution(* com.szwx.springmvc.*.controller.*.*(..))")
public void pointcut() {
}
// 方法执行前调用
@Before(value = "pointcut()")
public void before() {
//System.out.println("在方法执行前调用!");
}
// 方法执行后调用
@After(value = "pointcut()")
public void after() {
//System.out.println("方法执行后调用!");
}
// 方法执行的前后调用
@Around("pointcut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
String clazzString = point.getTarget().getClass().getName();
String methodName = point.getSignature().getName();
String fullPath = clazzString + "." + methodName;
int flag = clazzString.indexOf("$");
if (flag < 0)
log.info("开始业务处理[" + methodName + "];全路径[" + fullPath + "]");
long time = System.currentTimeMillis();
Object retVal = point.proceed();
time = System.currentTimeMillis() - time;
if (flag < 0)
log.info("结束业务处理[" + methodName + "];耗时:" + time + "毫秒;全路径[" + fullPath + "]");
return retVal;
}
// @AfterThrowing(pointcut="pointcut()")
// 如果使用该种写法则无法给doThrowing添加Throwable ex
// 参数,如没有该参数我们无法获悉程序运行的错误:error at ::0 formal unbound in pointcutd
// 故可修改成为如下:
@AfterThrowing(pointcut = "pointcut()", throwing = "ex")
public void doThrowing(JoinPoint jp, Throwable ex) {
PropertiesHelper g4PHelper = PropertiesFactory.getPropertiesHelper(PropertyFiles.APP);
String exceptionMonitor = g4PHelper.getValue("exceptionMonitor");
if (exceptionMonitor.equals("0")) {
return;
}
String clazzString = jp.getTarget().getClass().getName();
String methodName = jp.getSignature().getName();
String fullPath = clazzString + "." + methodName;
int flag = clazzString.indexOf("$");
if (flag < 0) {
log.info("业务处理时发生了异常:[" + fullPath + "]");
// ex.printStackTrace();
log.info("[异常类:"+clazzString+"],"+"[异常方法:"+methodName+"]"+"[异常信息:"+ex.getMessage()+"]");
}
}
}
2在spring 配置文件中添加aop命名空间,然后加入
<aop:aspectj-autoproxy proxy-target-class="true"/> 这里proxy-target-class="true"表示使用cglib进行代理
使用到的jar:cglib-nodep,aspectjweaver,aspectjtools,spring-asm
说明:当使用aop进行异常记录时,一些dao抛出的异常,如sqlexception等当事务由spring代理时,并不是立即抛出异常的,所以在这里是无法记录到的,经测试,在service中捕捉dao层的异常,如发生主键冲突,并不会立即捕获到异常,只有在spring提交事务以后才能知道异常,这些异常只能在controller层才能进行捕获,除非手动执行事务。
据说spring aop无法代理struts的action层,但是springmvc的controller经测试有效。
但是要在springmvc.xml中添加<aop:aspectj-autoproxy proxy-target-class="true"/>