Spring boot event事件Publisher|Listener

305 阅读1分钟

题记

该方法适用于消息发布消费的场景,支持异步,可以理解为更为解耦的线程池,更灵活的用法可以服务A引用服务B的maven依赖,B发布A消费,感兴趣可以自己试下。目前我用到的场景都是单服务内的异步。

graph TD
Publisher --> event -->listener

上代码

先建立好一个事件对象

其中PurchaseOrderInfo orderInfo就是我们要传递的数据

public class SaveRedundancyEvent extends ApplicationEvent {

    private PurchaseOrderInfo orderInfo;

    public SaveRedundancyEvent(PurchaseOrderInfo source) {
        super(source);
        this.orderInfo = source;
    }

    public PurchaseOrderInfo getOrderInfo() {
        return orderInfo;
    }

    public void setOrderInfo(PurchaseOrderInfo orderInfo) {
        this.orderInfo = orderInfo;
    }
}

数据生产者|消息发布者

先引入spring的发布对象

@Resource
private ApplicationEventPublisher applicationEventPublisher;

再将刚才的event进行发布

applicationEventPublisher.publishEvent(new SaveRedundancyEvent(orderInfo));

监听者|消息消费者

import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;

@Component
public class EventListener {

    @Resource
    private SearchOptionService searchOptionService;

    @org.springframework.context.event.EventListener
    @Async("taskExecutor")
    public void listener(SaveRedundancyEvent saveRedundancyEvent) throws InterruptedException {

        PurchaseOrderInfo orderInfo = saveRedundancyEvent.getOrderInfo();
        // 然后拿着orderInfo做业务处理即可

    }

}

线程池配置

上方@Async("taskExecutor")实际就是线程池的配置

@EnableAsync
@Configuration
public class SpringThreadPoolConfig {

    @Value("${mythreadpool.maxPoolSize}")
    private Integer maxPoolSize;
    @Value("${mythreadpool.corePoolSize}")
    private Integer corePoolSize;
    @Value("${mythreadpool.queueCapacity}")
    private Integer queueCapacity;
    @Value("${mythreadpool.keepAliveSeconds}")
    private Integer keepAliveSeconds;
    @Value("${mythreadpool.threadNamePrefix}")
    private String threadNamePrefix;
    @Value("${mythreadpool.waitForTasksToCompleteOnShutdown}")
    private Boolean waitForTasksToCompleteOnShutdown;

    @Bean("taskExecutor")
    public Executor asyncServiceExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置核心线程数等于系统核数--8核
        int availableProcessors = Runtime.getRuntime().availableProcessors();
        executor.setCorePoolSize(availableProcessors);
        // 设置最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        //配置队列大小
        executor.setQueueCapacity(queueCapacity);
        // 设置线程活跃时间(秒)
        executor.setKeepAliveSeconds(keepAliveSeconds);
        // 线程满了之后由调用者所在的线程来执行
        // 拒绝策略:CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 设置默认线程名称
        executor.setThreadNamePrefix(threadNamePrefix);
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(waitForTasksToCompleteOnShutdown);
        //执行初始化
        executor.initialize();
        return executor;
    }
}

具体要配什么参数可以去百度自行修改

mythreadpool:
  maxPoolSize: 20
  corePoolSize: 8
  queueCapacity: 2048
  keepAliveSeconds: 60
  threadNamePrefix: springThreadPool
  waitForTasksToCompleteOnShutdown: true