
本文旨在解释 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,并使用依赖注入:
这是推荐的解决方案。让 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中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号