我可以使用弹簧AOP记录方法的开始和结束,以帮助轻松调配

时间:2014-12-30 23:20:40

标签: spring spring-aop

我使用testNg测试应用程序并使用SpringTest。

我想记录每个方法的开始和结束,以便我可以轻松调试失败发生的地方

如果我有这样的方法

public void performUserSignIn(){      
     signInAgent.performSignIn(username,password);      
}

我希望像这样记录此方法的开始和结束

public void performUserSignIn(){      
     logger.info("started performUsersignIn");
     signInAgent.performSignIn(username,password);
     logger.info("finished performUsersignIn");      
}
对于我的测试自动化中的每个方法来说,这非常麻烦。我可以使用Spring AOP实现这一目标吗?我的想法是创建一个自定义注释@LogMessage,然后将其用作

@LogMessage("performUserSignIn")    
public void performUserSignIn(){      
     logger.info("started performUsersignIn");
     signInAgent.performSignIn(username,password);
     logger.info("finished performUsersignIn");      
}

甚至更喜欢这个

@LogMessage
public void performUserSignIn(){      
     logger.info("started performUsersignIn");
     signInAgent.performSignIn(username,password);
     logger.info("finished performUsersignIn");      
}

甚至可以这样做吗?

2 个答案:

答案 0 :(得分:1)

您需要使用@Around建议。示例代码应如下所示

@Aspect
public class MethodLogging {

@Around(execution("@annotation(LogMessage)"))
public Object logStartAndEnd(ProceddingJoinPoint pjp){
    String name = pjp.getSignature().getName();
    logger.info("started " + name);
    Object obj = pjp.proceed();
    logger.info("finished " + name); 
    return obj;
}

}

有关其他信息,请参阅相应的java文档。

答案 1 :(得分:0)

不要重新发明轮子,所以请看其他人收集有用的AOP,以便在你的项目中重复使用:-))开源是一个很好的社区:https://github.com/jcabi/jcabi-aspects

但如果您只想寻找自定义快速解决方案,那么在使用Spring时您可以通过以下方式满足您的要求:

pushd
call sejda.bat ...
popd

配置bean:

public class MyPerformanceMonitorInterceptor extends AbstractMonitoringInterceptor {

    public MyPerformanceMonitorInterceptor() {
    }

    public MyPerformanceMonitorInterceptor(boolean useDynamicLogger) {
            setUseDynamicLogger(useDynamicLogger);
    }

    @Override
    protected Object invokeUnderTrace(MethodInvocation invocation, Log log) 
      throws Throwable {
        String name = createInvocationTraceName(invocation);
        long start = System.currentTimeMillis();
        log.info("Method " + name + " execution started at:" + new Date());
        try {
            return invocation.proceed();
        }
        finally {
            long end = System.currentTimeMillis();
            long time = end - start;
            log.info("Method "+name+" execution lasted:"+time+" ms");
            log.info("Method "+name+" execution ended at:"+new Date());

            if (time > 10){
                log.warn("Method execution longer than 10 ms!");
            }            
        }
    }
}

将产生:

@Pointcut("execution(public int com.baeldung.performancemonitor.PersonService.getAge(..))")
public void myMonitor() { }

@Bean
public MyPerformanceMonitorInterceptor myPerformanceMonitorInterceptor() {
    return new MyPerformanceMonitorInterceptor(true);
}

@Bean
public Advisor myPerformanceMonitorAdvisor() {
    AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
    pointcut.setExpression("com.baeldung.performancemonitor.AopConfiguration.myMonitor()");
    return new DefaultPointcutAdvisor(pointcut, myPerformanceMonitorInterceptor());
}

最后注意:AOP在某些高性能场景中不是最佳选择,但最好考虑“事件中间件”实现......