前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >springboot实战之事件驱动模型

springboot实战之事件驱动模型

作者头像
lyb-geek
发布2019-08-12 15:00:13
3.7K0
发布2019-08-12 15:00:13
举报

前言

假设有这么一种业务场景,业务A处理完后,同时触发B、C、D业务执行,在不利用MQ的情况下,会有什么样的解决思路?可能的解决思路有如下 1、业务A处理后,开启线程处理B、C、D 2、使用disruptor进行处理 3、生产消费者模式 4、观察者模式 ... 解决的思路有多种多样,这边介绍一种思路->事件驱动模式,事件驱动模式与观察者模式在某些方面极为相似:当一个主体发生改变时,所有依属体都得到通知。不过,观察者模式与单个事件源关联,而事件驱动模式则可以与多个事件源关联。本文就介绍一下基于spring实现的事件驱动

spring事件驱动组成

spring事件驱动由3个部分组成

1、ApplicationEvent:表示事件本身,自定义事件需要继承该类。用来定义事件

2、ApplicationEventPublisherAware:事件发送器,需要实现该接口。主要用来发布事件

3、ApplicationListener:事件监听器接口。监听类实现ApplicationListener 里onApplicationEvent方法即可

spring事件驱动示例

示例演示了当数据库信息配置发生变更时,通过事件驱动异步变更spring的数据库配置信息bean,并通过定时器输出数据库配置信息。

本例子没有用ApplicationListener接口来实现监听。在spring4.2+推出了更优雅,基于注解的方式@EventListener来实现

1、发布事件

@Service
public class JdbcConfigServiceImpl implements JdbcConfigService, ApplicationEventPublisherAware {

    @Autowired
    private Mapper dozerMapper;

    @Autowired
    ApplicationEventPublisher applicationEventPublisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    @Override
    public String refreshJdbcConfig(JdbcConfigDTO jdbcConfigDTO) {
        JdbcConfig jdbcConfig = dozerMapper.map(jdbcConfigDTO,JdbcConfig.class);
        JdbcConfig cacheJdbcConfig = CacheJdbcConfigUtil.INSTANCE.getjdbcConfig();
        JdbcConfig changeFieldJdbcConfig = getChangeJdbcConfig(jdbcConfig, cacheJdbcConfig);

        if(StringUtils.isBlank(changeFieldJdbcConfig.getDriverClassName()) && StringUtils.isBlank(changeFieldJdbcConfig.getPassword())
                && StringUtils.isBlank(changeFieldJdbcConfig.getUrl())&& StringUtils.isBlank(changeFieldJdbcConfig.getUsername())){
            applicationEventPublisher.publishEvent("noChange");
            return "no change";
        }
        applicationEventPublisher.publishEvent(changeFieldJdbcConfig);
        return "refresh success";
    }

2、定义事件源以及监听器

@EventListener
    @Async
    public void changeRegisterBean(JdbcConfig jdbcConfig){
      log.info("refresh {}",jdbcConfig);
      JdbcConfig config = CacheJdbcConfigUtil.INSTANCE.refreshAndGet(jdbcConfig);
      BeanUtils.copyProperties(config,this.jdbcConfig);
      System.out.println(config);
    }

注:方法参数JdbcConfig jdbcConfig就是事件源

spring事件驱动注意点

  • 事件没要处理的监听器,就会被抛弃。
  • 一个事件可以同时被多个监听处理类监听处理。
  • 默认情况下事件是同步的,即事件被publish后会等待Listener的处理。如果发布事件处的业务存在事务,监听器处理也会在相同的事务中。
  • 如果对于事件的处理不想受到影响,可以onApplicationEvent方法上加@Aync支持异步/在有@EventListener的注解方法上加上@Aync。注:启动类上同时要加上@EnableAsync

利用@TransactionalEventListener实现监听事件时的事务隔离

@TransactionalEventListener和@EventListener都可以监听事件,但前者可以对发布事件和监听事件进行一些事务上的隔离。@TransactionalEventListener指不和发布事件的方法在同一个事务内,发布事件的方法事务结束后才会执行本监听方法,监听逻辑内发生异常不会回滚发布事件方法的事务。

@TransactionalEventListener有一个属性为fallbackExecution,默认为false,指发布事件的方法没有事务控制时,监听器不进行监听事件,此为默认情况!fallbackExecution=true,则指发布事件的方法没有事务控制时,监听方法仍可以监听事件进行处理。

总结

你有一件事情,做这件事情的过程包含了许多职责单一的子过程,而这些子过程有如下特点

  • 这些子过程有一定的执行次序;
  • 这些子过程之间需要较灵活的跳转;
  • 这些子过程也许需要围绕同一个上下文做操作;

此时就可以采用事件驱动模式,从而使得各个子过程的开发可以专注于自己的业务。

参考文档

SpringCloud工作笔记078---SpringBoot中使用sping事件驱动模型 https://blog.csdn.net/lidew521/article/details/94403577

事件驱动模型和观察者模式 https://blog.csdn.net/asdfsadfasdfsa/article/details/78175567

demo链接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-event-driven

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Linyb极客之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • spring事件驱动组成
  • spring事件驱动示例
  • spring事件驱动注意点
  • 利用@TransactionalEventListener实现监听事件时的事务隔离
  • 总结
  • 参考文档
  • demo链接
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档