Spring+EventBus实现异步事件

本文介绍了如何在Spring框架中使用EventBus进行异步事件发布,并通过ThreadPoolFactory创建定制化的线程池来处理这些事件。作者展示了如何集成Spring和EventBus,以及如何配置线程池以优化性能。
摘要由CSDN通过智能技术生成

Spring+EventBus实现异步事件

上代码

Maven依赖
<!-- guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>30.0-android</version>
</dependency>
ThreadPoolFactory
/**
 * 线程池工厂
 */
public final class ThreadPoolFactory {

	/**
	 * 默认最大并发数<br>
	 */
	private static final int DEFAULT_MAX_CONCURRENT = Runtime.getRuntime().availableProcessors() * 2;

	/**
	 * 默认线程存活时间
	 */
	private static final long DEFAULT_KEEP_ALIVE = 60L;

	/**
	 * 默认队列大小
	 */
	private static final int DEFAULT_SIZE = 1024;

	/**
	 * 线程池名称格式
	 */
	private static final String DEFAULT_THREAD_POOL_NAME = "ProcessPool-{}-%d";


	/**
	 * 创建默认的线程池
	 * @return ThreadPoolExecutor
	 */
	public static ExecutorService createDefThreadPool(){
		return createInitThreadPool(DEFAULT_MAX_CONCURRENT, DEFAULT_MAX_CONCURRENT * 4, DEFAULT_KEEP_ALIVE,
				TimeUnit.SECONDS, DEFAULT_SIZE, DEFAULT_THREAD_POOL_NAME, new ThreadPoolExecutor.CallerRunsPolicy());
	}


	/**
	 * 创建默认的线程池
	 *
	 * @param poolName 线程池名称
	 * @return ThreadPoolExecutor
	 */
	public static ExecutorService createDefThreadPool(String poolName){
		return createInitThreadPool(DEFAULT_MAX_CONCURRENT, DEFAULT_MAX_CONCURRENT * 4, DEFAULT_KEEP_ALIVE,
				TimeUnit.SECONDS, DEFAULT_SIZE, poolName, new ThreadPoolExecutor.CallerRunsPolicy());
	}

	/**
	 * 创建默认的线程池
	 *
	 * @param maxConcurrent 最大线程数
	 * @param poolName 线程池名称
	 * @return ThreadPoolExecutor
	 */
	public static ExecutorService createDefThreadPool(int maxConcurrent, String poolName){
		return createInitThreadPool(maxConcurrent, maxConcurrent * 4, DEFAULT_KEEP_ALIVE,
				TimeUnit.SECONDS, DEFAULT_SIZE, poolName, new ThreadPoolExecutor.CallerRunsPolicy());
	}

	/**
	 * 创建线程池
	 * @param coreConcurrent 核心线程数
	 * @param maxConcurrent 最大线程数
	 * @param keepAlive 线程存活时效
	 * @param timeUnit 线程存活单位
	 * @param queueSize 队列大小
	 * @param poolName 线程池名称
	 * @param handler 拒绝处理策略
	 * @return ThreadPoolExecutor
	 */
	public static ExecutorService createInitThreadPool(final int coreConcurrent,
														  final int maxConcurrent,
														  final long keepAlive,
														  final TimeUnit timeUnit,
														  final int queueSize,
														  final String poolName,
														  final RejectedExecutionHandler handler
														  ){
		return TtlExecutors.getTtlExecutorService(new ThreadPoolExecutor(coreConcurrent, maxConcurrent, keepAlive, timeUnit,
				new LinkedBlockingDeque<>(queueSize),
				new ThreadFactoryBuilder().setNameFormat(poolName).build(),
				handler
		));
	}

	private ThreadPoolFactory(){}

}
IEventBus
/**
 * EventBus 接口
 */
public interface IEventBus {
    /**
     * 发布事件
     * @param event 事件实体
     */
    void post(Object event);

    /**
     * 添加消费者
     * @param obj 消费者对象,默认以class为key
     */
    void addConsumer(Object obj);

    /**
     * 移除消费者
     * @param obj 消费者对象,默认以class为key
     */
    void removeConsumer(Object obj);

    /**
     * 扫描消费者
     * @param packageName 扫描包
     */
    void scanConsumer(String packageName);
}
IEventConsumer
/**
 * EventBus 消费者接口
 */
public interface IEventConsumer<T> {

    /**
     * 消费者事件
     * @param event 事件
     */
    void consumer(T event);

}
AbstractSpringEventBus
/**
 * EventBus 与 Spring 打通桥梁
 */
@Slf4j
public abstract class AbstractSpringEventBus implements IEventBus, ApplicationContextAware {
    private ApplicationContext context;

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

    @Override
    public void scanConsumer(String packageName) {
        context.getBeansOfType(IEventConsumer.class).forEach((k,v)->{
            this.addConsumer(v);
        });
    }
}
SpringEventBus
/**
 * 操作日志事件 总线
 */
@Component
@Slf4j
public class SpringEventBus extends AbstractSpringEventBus implements  SubscriberExceptionHandler {

    private final EventBus eventBus;

    public SpringEventBus() {
    	// 异步事件配置线程池
        eventBus = new AsyncEventBus(
                ThreadPoolFactory.createInitThreadPool(5, 10, 60, TimeUnit.SECONDS,
                1024, "Event-Bus",
                        new ThreadPoolExecutor.CallerRunsPolicy()
                        )
                , this
        );
    }

    @Override
    public void post(Object event) {
        eventBus.post(event);
    }

    @Override
    public void addConsumer(Object obj) {
        eventBus.register(obj);
    }

    @Override
    public void removeConsumer(Object obj) {
        eventBus.unregister(obj);
    }

    @Override
    public void handleException(Throwable exception, SubscriberExceptionContext context) {
        log.error("user event handler exception", exception);
    }

}
Test
/**
 * 被监听的事件
 */
@Data
public class Test implements Serializable {

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

}
TestEvent
/**
 * 事件的监听者
 */
@Slf4j
@Component
public class UnbindPhoneEvent implements IEventConsumer<Test> {

    @Override
    @Subscribe
    public void consumer(Test event) {
        log.info("监听到:{}",event.getName())
    }
}
事件发布
@AllArgsConstructor
@RestController
public class TestController {
    private final SpringEventBus springEventBus;
    
    public void testMain(){
        // 创建事件对象
        Test test = new Test();
        test.setName("xx");
        
        // 发送事件
        springEventBus.post(test);
    }
}
  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值