假设有这么一种业务场景,业务A处理完后,同时触发B、C、D业务执行,在不利用MQ的情况下,会有什么样的解决思路?可能的解决思路有如下 1、业务A处理后,开启线程处理B、C、D 2、使用disruptor进行处理 3、生产消费者模式 4、观察者模式 ... 解决的思路有多种多样,这边介绍一种思路->事件驱动模式,事件驱动模式与观察者模式在某些方面极为相似:当一个主体发生改变时,所有依属体都得到通知。不过,观察者模式与单个事件源关联,而事件驱动模式则可以与多个事件源关联。本文就介绍一下基于spring实现的事件驱动
spring事件驱动由3个部分组成
1、ApplicationEvent:表示事件本身,自定义事件需要继承该类。用来定义事件
2、ApplicationEventPublisherAware:事件发送器,需要实现该接口。主要用来发布事件
3、ApplicationListener:事件监听器接口。监听类实现ApplicationListener 里onApplicationEvent方法即可
示例演示了当数据库信息配置发生变更时,通过事件驱动异步变更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就是事件源
@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
https://github.com/lyb-geek/springboot-learning/tree/master/springboot-event-driven