首页 > Java > java教程 > 正文

Spring 中 @PostConstruct 执行两次的原因及解决方案

DDD
发布: 2025-07-19 17:34:10
原创
775人浏览过

spring 中 @postconstruct 执行两次的原因及解决方案

本文旨在解释 Spring 应用中 @PostConstruct 注解修饰的方法被执行两次的原因,并提供相应的解决方案。通常,这种情况是由于存在多个 Spring 上下文导致 Bean 被重复创建和初始化。理解 Spring 上下文的创建和管理是解决此问题的关键。

问题分析

在 Spring 应用中,@PostConstruct 注解用于标记在 Bean 初始化完成后需要执行的方法。Spring 容器负责管理 Bean 的生命周期,并在 Bean 实例化并完成依赖注入后调用被 @PostConstruct 注解的方法。

当 @PostConstruct 方法被执行多次时,通常是因为存在多个 Spring 容器实例。每个容器都会管理自己的 Bean,并按照生命周期管理 Bean 的初始化过程,因此会导致 @PostConstruct 方法被多次调用。

在您提供的代码示例中,问题在于 TextFilter 类中手动创建了一个新的 AnnotationConfigApplicationContext 实例:

public class TextFilter {
    private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    private MyCache<MyData> cache;

    public TextFilter() {
        this.context.scan("com.sensitive_words.utils");
        this.context.refresh();
        this.cache = this.context.getBean(MyCache.class);
    }

    public String filter(String originalText) {
        return this.cache.get().filter(originalText);
    }
}
登录后复制

TextFilter 的构造函数创建并刷新了一个新的 Spring 容器。这意味着除了主应用程序上下文(由 SensitiveWordsApplication 创建)之外,还存在第二个容器。MyCache Bean 在这两个容器中都会被创建,因此 @PostConstruct 方法会被调用两次。

解决方案

解决此问题的关键在于避免创建不必要的 Spring 容器。应该只使用主应用程序上下文来管理 Bean。

以下是几种可行的解决方案:

1. 将 TextFilter 也声明为一个 Bean,并使用依赖注入:

因赛AIGC
因赛AIGC

因赛AIGC解决营销全链路应用场景

因赛AIGC 73
查看详情 因赛AIGC

这是推荐的解决方案。让 Spring 管理 TextFilter 的生命周期,并将其依赖的 MyCache Bean 注入到 TextFilter 中。

@Component
public class TextFilter {

    private final MyCache<MyData> cache;

    @Autowired
    public TextFilter(MyCache<MyData> cache) {
        this.cache = cache;
    }

    public String filter(String originalText) {
        return this.cache.get().filter(originalText);
    }
}
登录后复制

确保 TextFilter 类被 Spring 容器扫描到。可以通过在包含 TextFilter 的包上添加 @ComponentScan 注解,或者使用 @Component 注解标记 TextFilter 类来实现。

2. 从主应用程序上下文中获取 MyCache Bean:

如果由于某些原因无法将 TextFilter 声明为 Bean,则可以从主应用程序上下文中获取 MyCache Bean。这需要访问主应用程序上下文,可以通过 ApplicationContextAware 接口来实现。但是,这种方法不太推荐,因为它使得 TextFilter 类与 Spring 容器耦合。

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class TextFilter implements ApplicationContextAware {

    private MyCache<MyData> cache;
    private ApplicationContext applicationContext;

    public TextFilter() {
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        this.cache = this.applicationContext.getBean(MyCache.class);
    }

    public String filter(String originalText) {
        return this.cache.get().filter(originalText);
    }
}
登录后复制

3. 移除手动创建的 ApplicationContext:

最简单的解决方案是直接删除 TextFilter 中手动创建的 AnnotationConfigApplicationContext,但这通常不可行,因为 TextFilter 可能需要依赖于Spring管理的Bean。

总结

@PostConstruct 方法被多次执行通常是由于存在多个 Spring 容器实例。通过避免手动创建 Spring 容器,并使用依赖注入来管理 Bean,可以有效地解决这个问题。推荐将所有需要使用 Spring 管理的 Bean 都交给 Spring 容器管理,避免手动创建容器。理解 Spring 上下文的生命周期和 Bean 的管理是解决此类问题的关键。

以上就是Spring 中 @PostConstruct 执行两次的原因及解决方案的详细内容,更多请关注php中文网其它相关文章!

相关标签:
最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
热门推荐
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号