[Java Framework] 解决监听ContextRefreshedEvent事件执行多次问题

简介: 搜索引擎很多答案都是未加测试,对想当然的“解决方案”以讹传讹,本文将从多个方面找到最低一个解决方案!

简介

搜索引擎很多答案都是未加测试,对想当然的“解决方案”以讹传讹,本文将从多个方面找到最低一个解决方案!

  • 始作俑者是对下面一段代码

“容器已经初始化”会出现多次的情况进行解决

@Component
public class MyApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        System.out.println("容器已经初始化");
        
    }
}

解释:
在web开发中会存在这样问题, 项目会存在两个容器,一个是spring的ioc容器(父),一个是springmvc的ioc容器(子),这两个容器是父子关系。这样就会造成onApplicationEvent方法被执行两次。为了解决此问题,我们可以判断当前容器是否父容器,是父容器才执行下边的代码。

方法 / 步骤

ContextRefreshedEvent ApplicationContext 被初始化或刷新时,该事件被触发。这也可以在 ConfigurableApplicationContext接口中使用 refresh() 方法来发生。此处的初始化是指:所有的Bean被成功装载后处理Bean被检测,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用

❌方案一: 判断是否是父容器进行触发(测试无效)

@Component
public class MyApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        ApplicationContext parent = contextRefreshedEvent.getApplicationContext().getParent();
        if (parent == null){
            System.out.println("容器已经初始化");
        }

    }
}

❌方案二: 判断DisplayName是否是Root容器进行触发(测试无效)

@Component
public class MyApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
    @Autowired
    private ApplicationContext applicationContext;
       if ("Root WebApplicationContext”".equals(contextRefreshedEvent.getApplicationContext().getDisplayName())) {
            //需要执行的方法
            System.out.println("容器已经初始化");
        }

}
如果想 ApplicationListener 只执行一次,那就只应该把它配置在 其中一个ApplicationContext 中,另外一个ApplicationContext 不配置。也就是说,使ApplicationListener的实现类,只被其中一个ApplicationContext 加载到。

✅方案三: 把ContextRefreshedEvent改成ApplicationReadyEvent事件 (测试可用)

@Component
public class BizListenerInitializer implements ApplicationListener<ApplicationReadyEvent> {
    @Override
    public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
        System.out.println("容器已经初始化");
    }
}

✅方案四: 在Bus总线监听异步事件业务场景

业务中使用消息总线做异步操作,对自定义事件进行实例化时候,通过唯一ID和时间戳方式做幂等操作!

参考资料 & 致谢

目录
相关文章
|
6月前
|
存储 机器学习/深度学习 监控
如何监控员工的电脑——基于滑动时间窗口的Java事件聚合算法实现探析​
在企业管理场景中,如何监控员工的电脑操作行为是一个涉及效率与合规性的重要课题。传统方法依赖日志采集或屏幕截图,但数据量庞大且实时性不足。本文提出一种基于滑动时间窗口的事件聚合算法,通过Java语言实现高效、低资源占用的监控逻辑,为如何监控员工的电脑提供一种轻量化解决方案。
148 3
|
6月前
|
JavaScript 前端开发 Java
【Java进阶】详解JavaScript事件
总的来说,JavaScript事件是JavaScript交互设计的核心,理解和掌握JavaScript事件对于编写高效、响应式的网页应用至关重要。
111 15
|
9月前
|
Java 开发者 Spring
java springboot监听事件和处理事件
通过上述步骤,开发者可以在Spring Boot项目中轻松实现事件的发布和监听。事件机制不仅解耦了业务逻辑,还提高了系统的可维护性和扩展性。掌握这一技术,可以显著提升开发效率和代码质量。
225 33
|
9月前
|
Java 开发者 Spring
java springboot监听事件和处理事件
通过上述步骤,开发者可以在Spring Boot项目中轻松实现事件的发布和监听。事件机制不仅解耦了业务逻辑,还提高了系统的可维护性和扩展性。掌握这一技术,可以显著提升开发效率和代码质量。
318 13
|
9月前
|
Java Spring
Java Spring Boot监听事件和处理事件
通过上述步骤,我们可以在Java Spring Boot应用中实现事件的发布和监听。事件驱动模型可以帮助我们实现组件间的松耦合,提升系统的可维护性和可扩展性。无论是处理业务逻辑还是系统事件,Spring Boot的事件机制都提供了强大的支持和灵活性。希望本文能为您的开发工作提供实用的指导和帮助。
344 15
|
9月前
|
Java 开发者 Spring
Java Springboot监听事件和处理事件
通过这些内容的详细介绍和实例解析,希望能帮助您深入理解Spring Boot中的事件机制,并在实际开发中灵活应用,提高系统的可维护性和扩展性。
439 7
|
11月前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
180 6
|
Java C#
Java的监听处理事件--小球移动案例
Java的监听处理事件--小球移动案例
77 0
|
12天前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
59 1

热门文章

最新文章