【发布时间】:2021-09-18 21:12:59
【问题描述】:
我想在正常关机方面做一些工作。
我尝试了如下所示的方法,但它不起作用。
我找到了一种解决方法(在 @EventListener 标记的 ContextClosedEvent 方法上添加方面注释),但我想了解它为什么失败(audit() 方法根本没有被调用,没有任何异常)。
@SpringBootApplication
public class Application {
public static void main(String args[]) {
SpringApplication.run(Application.class, args);
}
@AuditProcess
@PreDestroy
public void destroy() {
}
}
@Aspect
@Order(value = Ordered.HIGHEST_PRECEDENCE)
public class AuditProcessAspect {
@Pointcut("@annotation(com.aaa.bbb.annotation.AuditProcess) && execution(public * *(..))")
public void executionOfPublicAuditableMethod() {
}
@Around("executionOfPublicAuditableMethod()")
public Object audit(ProceedingJoinPoint joinPoint) {
// some business logic ...
}
}
就我深入研究 Spring 5 的内容而言,我发现 @PreDestroy 由 CommonAnnotationBeanPostProcessor 处理,@Aspect 类由 AspectJAdvisorFactory 转换为 Spring AOP Advisors(我猜是 JDK 代理上的 CGLIB)。因此,我不明白,为什么在将 SIGTERM 发送到应用程序的 JVM 进程后不调用方面逻辑。我什至检查了System.out.println(this.getClass().getCanonicalName()) 的输出,它被放入destroy() 方法的主体中——例如,它看起来像Application$$EnhancerBySpringCGLIB$$25f99bf7。从我目前的角度来看,没有什么可以阻止方面环绕 @PreDestroy 回调方法。
然而,它不起作用。
谁能解释一下原因?
【问题讨论】:
-
您能否详细说明失败/什么不起作用?有什么例外吗?
audit()method 的期望是什么?这个方法没有触发吗? -
@R.G 后者。
audit()方法包含一些日志记录逻辑(在调用编织目标方法之前和之后写入安全日志时间戳 + 目标方法名称,用 @AuditProcess 标记)。将 SIGTERM 发送到 JVM 进程后,我在安全日志中看不到任何记录,这看起来好像没有调用该方法。我曾尝试将System.out.println("aaabbb")添加到audit()正文中 - stdout 终端中没有输出。 -
AuditProcess注释保留策略是RUNTIME 吗? -
@R.G 是的,保留策略 RUNTIME 和目标 - 方法
-
你确定
AuditProcessAspect甚至被Spring的组件扫描发现了吗?您是否使用@Component(或类似)注释标记了方面类?