Spring Boot - Application Events 同步 VS 异步 发布订阅事件实战

这篇具有很好参考价值的文章主要介绍了Spring Boot - Application Events 同步 VS 异步 发布订阅事件实战。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


Spring Boot - Application Events 同步 VS 异步 发布订阅事件实战,【Spring Boot2.X】,spring boot,发布订阅

Pre

Spring Boot - Application Events 的发布顺序_ApplicationStartingEvent

Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent

Spring Boot - Application Events 的发布顺序_ApplicationContextInitializedEvent

Spring Boot - Application Events 的发布顺序_ApplicationPreparedEvent

Spring Boot - Application Events 的发布顺序_ContextRefreshedListener

Spring Boot - Application Events 的发布顺序_ApplicationStartedEvent

Spring Boot - Application Events 的发布顺序_AvailabilityChangeEvent

Spring Boot - Application Events 的发布顺序_ApplicationReadyEvent

Spring Boot - Application Events 的发布顺序_ApplicationFailedEvent

Spring Boot - ApplicationRunner && CommandLineRunner扩展接口


Code

Spring Boot - Application Events 同步 VS 异步 发布订阅事件实战,【Spring Boot2.X】,spring boot,发布订阅


基础工程

启动类

@SpringBootApplication 
public class LifeCycleApplication {

    /**
     * 除了手工add , 在 META-INF下面 的 spring.factories 里增加
     * org.springframework.context.ApplicationListener=自定义的listener 也可以
     *
     * @param args
     */
    public static void main(String[] args) {
        SpringApplication.run(LifeCycleApplication.class, args);

	}
}

META-INF中增加 spring.factories文件

org.springframework.context.ApplicationListener=\
com.artisan.practise.listeners.SpringBuiltInEventsListener

切入口

package com.artisan.practise.listeners;

import com.artisan.practise.publish.Publisher;
import org.springframework.beans.BeansException;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.event.SpringApplicationEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
public class SpringBuiltInEventsListener implements ApplicationListener<SpringApplicationEvent>, ApplicationContextAware {

    private ApplicationContext applicationContext;

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

    @Override
    public void onApplicationEvent(SpringApplicationEvent event) {
        System.out.println("SpringApplicationEvent Received - " + event);

        // Initializing publisher for custom event
        this.initPublisher(event);
    }

    private void initPublisher(SpringApplicationEvent event) {
        if (event instanceof ApplicationReadyEvent) {
            this.applicationContext.getBean(Publisher.class).publishEvent();
        }
    }
}
    

事件

package com.artisan.practise.events;

import org.springframework.context.ApplicationEvent;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
public class UserCreatedEvent extends ApplicationEvent {

	private static final long serialVersionUID = 1L;
	private String name;

	public UserCreatedEvent(Object source, String name) {
		super(source);
		this.name = name;
	}

	public String getName() {
		return this.name;
	}

}

package com.artisan.practise.events;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
public class UserRemovedEvent {

	public String name;

	public UserRemovedEvent(String name) {
		this.name = name;
	}

	public String getName() {
		return this.name;
	}

}



发布事件

package com.artisan.practise.publish;

import com.artisan.practise.events.UserCreatedEvent;
import com.artisan.practise.events.UserRemovedEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
@Component
public class Publisher {


    @Autowired
    private ApplicationEventPublisher publisher;

    public void publishEvent() {
        System.out.println("========================"  + Thread.currentThread().getName());
        // Async Event
        publisher.publishEvent("I'm Async");

        // @EventListener Annotated and ApplicationListener
        publisher.publishEvent(new UserCreatedEvent(this, "Artisan"));
        publisher.publishEvent(new UserRemovedEvent("Artisan"));

        // Conditional Listener
        publisher.publishEvent(new UserCreatedEvent(this, "reflectoring"));
        publisher.publishEvent(new UserRemovedEvent("reflectoring"));

    }

}
    

同步 Listener

package com.artisan.practise.listeners;

import com.artisan.practise.events.UserCreatedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
@Component
class UserCreatedListener implements ApplicationListener<UserCreatedEvent> {

	@Override
	public void onApplicationEvent(UserCreatedEvent event) {
		System.out.println(String.format("%s - User created: %s",Thread.currentThread().getName() , event.getName()));
	}
}

package com.artisan.practise.listeners;

import com.artisan.practise.events.UserRemovedEvent;
import com.artisan.practise.response.ReturnedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;

/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
@Component
public class UserRemovedListener {

    @EventListener
    ReturnedEvent handleUserRemovedEvent(UserRemovedEvent event) {
        System.out.println(String.format("%s - User removed (@EventListerner): %s", Thread.currentThread().getName(), event.getName()));
        // Spring will send ReturnedEvent as a new event
        return new ReturnedEvent();
    }

    // Listener to receive the event returned by Spring
    @EventListener
    void handleReturnedEvent(ReturnedEvent event) {
        System.out.println(String.format("%s - ReturnedEvent received.", Thread.currentThread().getName()));
    }

    @EventListener(condition = "#event.name eq 'reflectoring'")
    void handleConditionalListener(UserRemovedEvent event) {
        System.out.println(String.format("%s - User removed (Conditional): %s", Thread.currentThread().getName(), event.getName()));
    }

    @TransactionalEventListener(condition = "#event.name eq 'reflectoring'", phase = TransactionPhase.AFTER_COMPLETION)
    void handleAfterUserRemoved(UserRemovedEvent event) {
        System.out.println(String.format("%s - User removed (@TransactionalEventListener): %s", Thread.currentThread().getName(), event.getName()));
    }

}


异步Listener

增加@EnableAsync

启动类增加@EnableAsync

@SpringBootApplication
@EnableAsync
public class LifeCycleApplication {



}

@EnableAsync 是一个在 Spring 框架中使用的注解,它用于启用 Spring 的异步执行功能。当在一个配置类上加上 @EnableAsync 注解时,Spring 容器会设置异步任务执行的支持。这允许你将任务标记为异步,并且可以在不同的线程中执行它们,从而提高应用程序的响应能力和吞吐量。
以下是一些关键点,用以解释 @EnableAsync 注解的功能和用法:

  1. 异步执行: 在 Spring 应用中,你可以使用 @Async 注解来标记一个方法为异步执行。当方法被调用时,它将在一个单独的线程中运行,而不是在调用线程中立即执行。

  2. 启用异步执行: 为了使 @Async 注解生效,必须在 Spring 应用程序的配置中启用异步支持。这通常是通过在 Spring 配置类上添加 @EnableAsync 注解来实现的。

  3. 线程池: @EnableAsync 注解允许你定义一个自定义的线程池,Spring 会使用这个线程池来执行异步任务。如果你没有提供线程池,Spring 会使用默认的线程池。

  4. 异常处理: 异步方法执行中发生的异常通常不会传递给调用者。@EnableAsync 支持异常处理配置,允许你定义如何处理这些异常。

  5. 调度器: 你可以指定一个 TaskScheduler Bean,Spring 使用它来调度异步任务。默认情况下,Spring 容器会创建一个 SimpleAsyncTaskExecutor 实例。

  6. 顺序执行: 如果你需要确保某些异步方法按照严格的顺序执行,可以使用 @Async 注解的 dependsOn 属性来指定依赖关系。

使用 @EnableAsync 注解可以让开发者轻松地构建高并发的应用程序,提高应用程序处理大量并发请求的能力,同时保持代码的清晰和易管理性。在微服务架构和分布式系统中,异步通信是提高系统解耦和性能的关键技术之一。


增加 @Async

增加 @Async

package com.artisan.practise.listeners;

import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

@Component
class AsyncListener {

    @Async
    @EventListener
    void handleAsyncEvent(String event) {
        System.out.println(String.format("%s - Async event recevied: %s  ",  Thread.currentThread().getName(), event));
    }

}

@Async 是一个方法级别的注解,在 Spring 框架中用于标识一个方法应该以异步方式执行。当一个方法被标记为 @Async 时,它将在一个单独的线程中运行,而不是在调用它的线程中立即执行。这种方式可以避免阻塞调用线程,从而提高应用程序的响应能力和吞吐量。
以下是一些关于 @Async 注解的关键点:

  1. 异步方法执行: @Async 注解允许你将方法的执行放到一个单独的线程中,这样主线程就可以立即返回,继续处理其他任务。
  2. 线程池: @Async 注解通常与 @EnableAsync 注解一起使用,后者启用了异步支持并定义了一个线程池。异步方法通常会在这个线程池中分配线程来执行。
  3. 异常处理: 异步方法执行过程中出现的异常通常不会传递给调用者。但是,可以通过配置 AsyncUncaughtExceptionHandler 来处理这些异常。
  4. 调度器: @Async 注解可以指定一个 TaskScheduler Bean,它负责调度异步任务的执行。如果没有指定,Spring 会默认使用一个 SimpleAsyncTaskExecutor
  5. 顺序执行: 如果需要确保某些异步方法按照严格的顺序执行,可以使用 @Async 注解的 dependsOn 属性来指定依赖关系。
  6. 触发器: @Async 方法可以由其他 @Async 方法触发,这允许创建异步的工作流和回调。
  7. 注解兼容性: @Async 注解可以与 @Transactional 注解一起使用,但是需要确保事务性注解和异步注解在方法上的使用是兼容的。

异步编程 - 08 Spring框架中的异步执行_TaskExecutor接口和@Async应用篇

异步编程 - 09 Spring框架中的异步执行_@Async注解异步执行原理&源码解析


测试

Spring Boot - Application Events 同步 VS 异步 发布订阅事件实战,【Spring Boot2.X】,spring boot,发布订阅文章来源地址https://www.toymoban.com/news/detail-795882.html

到了这里,关于Spring Boot - Application Events 同步 VS 异步 发布订阅事件实战的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Boot - Application Events 的发布顺序_ApplicationContextInitializedEvent

    Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent Spring Boot 的广播机制是基于观察者模式实现的,它允许在 Spring 应用程序中发布和监听事件。这种机制的主要目的是为了实现解耦,使得应用程序中

    2024年01月17日
    浏览(45)
  • 【Spring Boot 3】【Redis】消息发布及订阅

    软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中,每次学习新技术总是要花费或多或少的时间、检索不止一篇资料才能得出一个可工作的DEMO,这占用了我大量的时

    2024年01月21日
    浏览(49)
  • Spring Boot整合RabbitMQ之发布与订阅模式

    RabbitMQ的模式中,常用的模式有:简单模式,发布与订阅模式,工作模式,路由模式,主题模式。简单模式不太会运用到工作中,我们可以使用 RabbitMQ 的发布订阅模式,实现: 用户发布动态,其“粉丝”收到其发布动态的消息 用户下订单,库存模块、支付模块等收到消息并

    2024年02月12日
    浏览(41)
  • Spring Boot进阶(62):Redis魔法:用发布订阅功能打造高效消息队列!

            话说,玩过MQ的同学可能都知道【发布订阅】模式,不就是一种消息传递方式嘛;如果没玩过,那也不打紧,下文我会简单做个科普。但是对于Redis如何实现MQ的【发布订阅】功能?这才是问题的关键,有的同学就说“压根没玩过呀!不造” ,哈哈,bug菌既然敢写便有

    2024年02月09日
    浏览(49)
  • SqlServer2016数据同步之使用发布/订阅功能同步数据

    登录服务器,使用Microsoft SQL Server Management Studio连接数据库,选择:复制-本地发布  右键-新建发布  下一步  选择快照文件夹  选择数据库  选择“事务发布”  选择表  下一步  设置执行时间 设置代理安全性  直接下一步,输入发布名称等待发布成功  右键属性,查看快

    2024年02月16日
    浏览(39)
  • .Net 6 下WorkerService+RabbitMq实现消息的异步发布订阅

            近期项目里有需要用到RabbitMq实现一些业务,学习整理之后在此记录一下,如有问题或者不对的地方,欢迎留言指正。 注意: 多线程消息发布时,应避免多个线程使用同一个IModel实例,必须保证Imodel被一个线程独享,如果必须要多个线程访问呢一个实例的话,则可以

    2024年01月18日
    浏览(51)
  • 【SpringBoot笔记34】Spring Events事件驱动编程之事件的发布和监听操作

    这篇文章,主要介绍Spring Events事件驱动编程之事件的发布和监听操作。 目录 一、基于接口实现 1.1、自定义事件 1.2、主动发布事件 1.3、监听事件对象

    2024年02月16日
    浏览(45)
  • SQL server 数据库同步(发布与订阅)【解决办法】

    注意:所有连接数据库操作时注意连接的数据库是否在所选服务器上 ![在这里插入图片描述](https://img-blog.csdnimg.cn/38812acbb640420b89ba666dd016adb8.png) 在 发布服务器 和 订阅服务器 本地防火墙放通1433端口 参考 【操作方法】windows防火墙添加出入站规则方法 此处选择影响代理管理位

    2024年02月16日
    浏览(32)
  • Python异步编程之web框架 异步vs同步 Redis并发对比

    主题: 比较异步框架和同步框架在RedisIO操作的性能差异 python版本 :python 3.8 数据库 :redis 5.0.7 压测工具 :locust web框架 :同步:flask 异步:starlette 请求并发量 : 模拟10个用户 服务器配置 : Intel(R) i7-12700F 客户端配置 :Intel(R) i7-8700 3.20GHz flask是python中轻量级web框架,特点是灵

    2024年02月10日
    浏览(46)
  • 使用spring自带的发布订阅来实现发布订阅

    公司的项目以前代码里面有存在使用spring自带发布订阅的代码,因此稍微学习一下如何使用,并了解一下这种实现方式的优缺点。 优点 实现方便,代码方面基本只需要定义消息体和消费者,适用于小型应用程序。 不依赖外部中间件,因而不需要复杂的配置、部署。 缺点 无

    2024年02月10日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包