在我现在使用的基于Spring的Web应用程序项目中,开发人员已经为每个函数编写了两个日志记录语句。一个将条目记录到函数中,另一个记录退出。我们的想法是追踪执行路径 - 至少是一个功能级别。
有没有办法在不乱丢整个代码库的情况下完成这些重复的语句?
要清楚,我们要记录所有函数,而不仅仅是Spring bean的公共方法。
答案 0 :(得分:4)
您可以使用Spring AOP执行此操作。
Spring AOP允许您在方法调用之前和/或之后“拦截”方法调用并执行任意代码。您还可以检查这些方法的参数和返回值。
要实现您正在谈论的日志记录,您可以使用around advice执行此类操作:
有关如何执行此操作的所有Spring详细信息都可以在提供的文档中找到。
答案 1 :(得分:0)
与尼古拉斯相同的想法。你可以使用Spring AOP来做到这一点。
我喜欢使用注释,因此逻辑在源代码中指定,而不是在方面的建议中。
定义注释
package aop;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Traceable {}
定义方面
package aop;
@Aspect
public class TraceableAspect {
private final static AtomicLong Count = new AtomicLong(0);
@Around("execution(* *(..)) && @annotation(aop.Traceable)")
public Object aroundTraceableMethod(ProceedingJoinPoint pjp) throws Throwable {
Logger logger = LoggerFactory.getLogger(pjp.getTarget().getClass());
if (logger.isTraceEnabled()) {
return executeWithTrace(pjp, logger, Count.incrementAndGet());
}
return pjp.proceed();
}
private Object executeWithTrace(ProceedingJoinPoint pjp, Logger logger, long id) throws Throwable {
long start = System.currentTimeMillis();
try {
logger.trace(String.format("#### - #%d - Starting execution of method '%s'", id, pjp.toShortString()));
return pjp.proceed();
} catch (Throwable throwable) {
logger.error(String.format("#### - #%d - Error while executing method '%s' : %s", id, pjp.toShortString(), throwable.toString()));
throw throwable;
} finally {
if (logger.isTraceEnabled()) {
logger.trace(String.format("#### - #%d - End of method '%s' (duration %s ms)", id, pjp.toShortString(), (System.currentTimeMillis() - start)));
}
}
}
}
使用Spring Boot项目中的方面
package project;
@Profile("with-trace-aop")
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class SecToolWebApplicationTraceableAspect extends aop.TraceableAspect {
@PostConstruct
public void init(){
Logger logger = LoggerFactory.getLogger(this.getClass());
logger.warn("###-AOP-### TraceableAspect initialized for this application");
}
}
**控制器中的跟踪方法
package project;
@RestController
public class ModelController {
@Traceable
@RequestMapping(method = RequestMethod.GET, value = "/{date}")
@ResponseBody
public <Collection<TE> find(@PathVariable @DateTimeFormat(pattern = DateUtils.DATE_FORMAT) Date date) {
...
}
}
重要当某个类与建议相关联时,不再调用所有“最终”方法。重要的是不要使用“最终”
因此,假设启用了TRACE模式日志,将跟踪方法“find”的每次调用
如果
,请注意这不起作用