我想在优雅的关闭上做一些工作。
我尝试了如下所示的方法,但它不起作用。
我找到了一个解决方法(在ContextClosedEvent的@EventListener标记方法上放置方面注释),但我想了解它失败的原因(Aud()
方法没有任何异常根本没有调用)。
@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(我猜是JDK代理上的CGLIB)转换为Spring AOP顾问。因此,我不明白为什么在将SIGTERM发送到应用程序的JVM进程后不调用方面逻辑。我甚至检查了<code>System.out.println(this.getClass())的输出。getCanonicalName()),它被放在<code>destroy()方法的主体中-例如,它看起来像是应用程序$$EnhancerBySpringCGLIB$$25f99bf7。从我目前的观点来看,没有什么可以阻止方面围绕@PreDestroy回调方法包装<然而,它不起作用<有人能解释一下原因吗?
如果您像 appContext.getBean(Application.class).destroy()
那样手动调用 pre-destroy 方法,则会触发该方面。但是,在应用程序被销毁的生命周期部分,似乎不再应用任何方面。
根据javadoc@PreDestroy
,带注释的目标方法可能是私有的,甚至是最终的,即两个特征与基于代理的Spring AOP用法相矛盾。我根本不是Spring或Java EE用户,我可能是错的,但对我来说,这似乎不应该按照你期望的方式工作。像M. Deinum或R.G这样的Spring专家也许能够更多地了解这个问题。
以下是我的分析<修改了code>main()方法以说明bean方法触发器。
@SpringBootApplication
public class MainApp {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplication(MainApp.class).run(args);
MainApp app = context.getBean(MainApp.class);
app.destroy();
}
@PreDestroy
@AuditProcess
public void destroy() {
System.out.println("PreDestroy");
}
}
当在 main() 方法中调用 app.destory
()
时,调用在代理上完成
MainApp$$EnhancerBySpringCGLIB$$f2c7a1b4(MainApp).destroy() line: 25
MainApp$$FastClassBySpringCGLIB$$8fbee297.invoke(int, Object, Object[]) line: not available
MethodProxy.invoke(Object, Object[]) line: 218
...
MyAspect.preDestroyLog(ProceedingJoinPoint) line: 27
...
CglibAopProxy$DynamicAdvisedInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 692
MainApp$$EnhancerBySpringCGLIB$$b98f9ed6.destroy() line: not available
MainApp.main(String[]) line: 18
当Application ationContext关闭时,生命周期回调是由实际对象而不是代理上的InitDestRoyAnNotationBeanPostProcencer$LifecycleMetadata.invokeDestroyMethods(Object, String)
完成的,因此不会发生任何建议。
MainApp$$EnhancerBySpringCGLIB$$f2c7a1b4(MainApp).destroy() line: 25
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 566
InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(Object) line: 389
InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeDestroyMethods(Object, String) line: 347
CommonAnnotationBeanPostProcessor(InitDestroyAnnotationBeanPostProcessor).postProcessBeforeDestruction(Object, String) line: 177
DisposableBeanAdapter.destroy() line: 242
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).destroyBean(String, DisposableBean) line: 587
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).destroySingleton(String) line: 559
DefaultListableBeanFactory.destroySingleton(String) line: 1152
DefaultListableBeanFactory(DefaultSingletonBeanRegistry).destroySingletons() line: 520
DefaultListableBeanFactory.destroySingletons() line: 1145
AnnotationConfigApplicationContext(AbstractApplicationContext).destroyBeans() line: 1111
AnnotationConfigApplicationContext(AbstractApplicationContext).doClose() line: 1080
AbstractApplicationContext$1.run() line: 996