Spring Boot @PreDestroy注解不起作用

8

我是一名新手,正在学习Spring Boot。我有一个Spring Boot应用程序,似乎忽略了@PreDestroy注释——当我从命令行或通过Eclipse运行时,当应用程序关闭(例如通过ctrl-c)时,我从未看到@PreDestroy代码被运行。

以下是代码...

Application.java:

@SpringBootApplication
public class Application {

    @Autowired
    private MessageProcessor messageProcessor;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @PostConstruct
    public void init() {    
        messageProcessor.run();
    }

}

消息处理器配置:

@Configuration
public class MessageProcessorConfiguration {

    @Bean
    public MessageProcessor messageProcessor() {
        return new MessageProcessorImpl();
    }
}

消息处理器:

public class MessageProcessorImpl implements MessageProcessor {

    @Override
    public void run() {

        while (isActive()) {
           …
        }
    }


   @PreDestroy
   public void shutdown() { 
       System.out.println("MessageProcessorImpl - shutting down");
   }

}

2
PreDestroy注解用于方法上作为回调通知,以表示实例正在被容器删除的过程中,它不是应用程序的预关闭。 - Azzabi Haythem
看一下这个问题:https://dev59.com/Z2Ag5IYBdhLWcg3wI4ER - Azzabi Haythem
阅读这个,看起来应该正在调用@PreDestroy... - finbin
1
不,如果这个bean不是单例的话,它会被调用多次。 - Azzabi Haythem
好的,你知道我应该如何捕获关机事件吗?-谢谢 - finbin
显示剩余4条评论
4个回答

3

Spring Boot在上下文创建期间注册关闭挂钩,请参见org.springframework.context.support.AbstractApplicationContext#registerShutdownHook方法。结果,如果您通过java -jar app.jar命令运行应用程序,并按下crtl+c组合键,则必须关闭上下文,从而触发您的@Predestroy方法。这对我有效。

我没有在您的代码中看到任何备注。我建议使用@ Component注释而不是手动的@Bean声明来注释您的MessageProcessorImpl bean。


2

当在bean上使用Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE)时,@PreDestroy不起作用,因为使用该方法生成的bean并不完全由IOC容器管理。

当在bean上使用Scope(value=ConfigurableBeanFactory.SCOPE_SINGLETON)时,@PreDestroy会起作用。


你能提供一些参考资料的链接吗? - gabkov
在Spring Boot 2.4.3中对我没有起作用。 - Tobias Meyer

-1

@PreDestroy 不会被调用,因为应用程序尚未完全初始化。这是由于在 init 方法上使用了 @PostConstruct,它作为 Spring 初始化的一部分被调用。

可以通过使用 CommandLineRunner 来解决此问题,它在 Spring 完全初始化后被调用:

@Component
public class Initializer implements CommandLineRunner {

    private final private MessageProcessor messageProcessor;

   public Initializer(MessageProcessor messageProcessor) {
       this.messageProcessor = messageProcessor;

    @Override
    public void run(String[] args) {
        messageProcessor.init();
    }
}

-1
尝试在你的XML中添加这行。
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" /> - user12059843
1
以下是与编程有关的内容,请将其从英语翻译成中文。仅返回翻译后的文本:请在回答正文中添加您的评论,并添加有关它如何解决问题的一些评论。Commenting your code is an important aspect of programming. It helps other developers understand what you are trying to accomplish with your code and makes it easier for them to modify or add to it in the future. Good commenting practices include using clear language, being concise, and explaining the reasoning behind why certain code was written. - Dmitriy Fialkovskiy
你好 @user12059843。你仍然可以[编辑]你的答案,并将该行添加到其中。 - TT.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接