eventbus做为事件总线能够提供消费者的注册和事件的分发功能,是实现事件驱动的必要工具也是项目中的解耦利器。html
本组件是基于greenrobot的eventbus包装,考虑到大部分项目都是基于spring开发,消费者提供了bean的自动注册。事件发布者也以单例bean的形式建立。java
使用示例:https://github.com/neuSnail/s...git
快速开始
maven依赖:github
<dependency> <groupId>com.github.neusnail</groupId> <artifactId>spring-eventbus</artifactId> <version>1.0</version> </dependency>
配置发布器web
@Configuration public class EventBusConfig { @Bean public EventPublisher eventPublisher() { return EventPublisherBuilder.createDefault(); } }
建立消费者和事件spring
@EventSubscriber @Slf4j //用户行为事件消费者 public class UserBehaviorSubscriber { @Subscribe() public void userLeaveSubscriber(UserEntryEvent event) { log.info("get userLeaveEvent userName:{}", event.getUserName()); } @Subscribe(threadMode = ThreadMode.ASYNC, priority = 1) public void userEntrySubscriber(UserLeaveEvent event) { log.info("get userEntryEvent userName:{}", event.getUserName()); } }
@Data @EqualsAndHashCode(callSuper = true) public class UserEntryEvent extends BaseEvent { private String userId; private String userName; }
开启消费者扫描异步
建议在main方法以后直接调用注册,也可使用@EventListener、CommandLineRunner、实现aware等方式在容器启动后注册,但注意确保不要重复注册async
@SpringBootApplication public class DemoApplication{ public static void main(String[] args) { ApplicationContext context = SpringApplication.run(DemoApplication.class, args); SubscriberRegister.register(context); } }
发送事件maven
public void postEvent() { UserEntryEvent userEntryEvent = new UserEntryEvent(); userEntryEvent.setUserName("bigBoss"); eventPublisher.post(userEntryEvent); }
注意这里提供的postAsync是生产方的异步,决定权在生产者这里,threadmode是消费方的异步,决定权在消费者里工具
参数配置
在注册publisher bean时候能够配置部分参数
@Configuration public class EventBusConfig { @Bean public EventPublisher eventPublisher() { return EventPublisherBuilder.builder() .asyncPostExecutor(Executors.newFixedThreadPool(1)) .EventBus(EventBus.builder() .throwSubscriberException(false) .sendNoSubscriberEvent(true) .executorService(Executors.newCachedThreadPool()) .build() ).build(); } }
其中asyncPostExecutor是发布者异步发送时使用的线程池,eventbus中的executorService是消费者异步消费的线程池
关于eventbus builder的具体参数文档可参照:https://greenrobot.org/files/...
默认的发送者和消费者线程池都使用了阿里的ttl线程池,避免父子线程传递问题
private ExecutorService defaultExecutor() { ThreadPoolExecutor executor = new ThreadPoolExecutor( 4, 8, 5L, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(1000), new ThreadPoolExecutor.CallerRunsPolicy() ); return TtlExecutors.getTtlExecutorService(executor); }
消费者线程模式和优先级
@subscribe中的threadmode有如下选项
ThreadMode.POSTING:和发送事件在同一个线程
ThreadMode.MAIN:主线程
ThreadMode.BACKGROUND:子线程
ThreadMode.ASYNC:异步线程
咱们在javaweb的开发中通常只会使用ThreadMode.POSTING(同步)和ThreadMode.ASYNC(异步)
priority是优先级,数值越大越先被消费