您的位置:首页 > 编程语言 > Java开发

SpringAOP注解方式监控方法执行情况

2016-03-15 09:42 639 查看
1、为什么要这么做?

答:有时候,我们需要监控一个方法的执行情况,比如花费时间、入参和结果,当然,我们可以直接在每个方法里面直接打印日志,但是这样太不灵活,每个方法需要的方法都要去加这样的代码,不需要时还要去掉,太麻烦了,不利于维护和重用。有没有一种方式,只需要在某个方法上添加一个注解,自然就可以监控此方法,不需要监控的时候,删除这个注解就可以了,有没有这样的解决方案呢?当然有。

2、如何做?

第一步:自定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RunStatus {

public String logLevel() default "debug";
}

说明:java的Annotation没有什么可说的,就是标识而已,记住如何定义使用即可。
第二步:定义一个切面

@Component
@Aspect
public class MonitorAspect {

private Logger logger = LoggerFactory.getLogger(MonitorAspect.class);

//切点(切入所有注解为RunStatus的方法)
@Pointcut("@annotation(com.hk515.mingyihuiinterface.annotation.RunStatus)")
public void runStatusAnnotation(){}

//通知(统计被切入方法的运行状态)
@Around("runStatusAnnotation()")
public Object runStatus(ProceedingJoinPoint point) throws Throwable{
Method[] methods = point.getSignature().getDeclaringType().getMethods();//methods[0]是当前point所在的方法
boolean annotationPresent = methods[0].isAnnotationPresent(RunStatus.class);
Object proceed = null;
if(annotationPresent){
long start = System.currentTimeMillis();
proceed = point.proceed();
long end = System.currentTimeMillis();

String logLevel = methods[0].getAnnotation(RunStatus.class).logLevel();//获取注解上所写的logLevel
String info = "\n方法:{}\n入参:{}\n结果:{}\n耗时:{}毫秒,{}秒";
if("debug".equals(logLevel)){
logger.debug(info,methods[0],point.getArgs(),proceed,end-start,(end-start)/1000);
}else if("info".equals(logLevel)){
logger.info(info,methods[0],point.getArgs(),proceed,end-start,(end-start)/1000);
}else{
logger.info(info,methods[0],point.getArgs(),proceed,end-start,(end-start)/1000);
}
}else{
proceed = point.proceed();
}
return proceed;
}
}


说明:还不懂SpringAOP的赶紧去学学,切面包含切点和通知,切点自然就是要切的位置了;通知有多种,意思是对所切位置的增强处理代码,我们把监控的逻辑写到这里即可。

第三步:如何使用?

直接在方法上加上@RunStatus注解就可以了。

@RunStatus
public ModelResult<List<Area>> fetch(){
//
}

备注:记得在spring配置文件中开启aop代理,<aop:aspectj-autoproxy />

总结:原理也很简单,就是spring在启动的时候会扫描所有的方法,一旦发现某个方法上有@RunStatus注解,就会为此类生成代理类,并给将此方法用runStatus(ProceedingJoinPoint point) 包裹起来,执行目标方法前后会执行我们写的runStatus(ProceedingJoinPoint point)方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息