Spring Boot ApplicationListener异步执行

Spring Boot版本

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot</artifactId>
    <version>1.3.6.RELEASE</version>
</dependency>

查阅代码会发现,事件的执行在类:SimpleApplicationEventMulticaster

代码块:

private Executor taskExecutor;

protected Executor getTaskExecutor() {
    return this.taskExecutor;
}

@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
        Executor executor = getTaskExecutor();
        if (executor != null) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    invokeListener(listener, event);
                }
            });
        }
        else {
            invokeListener(listener, event);
        }
    }
}

设置方法:

@Bean
public SmartInitializingSingleton applicationEventMulticasterInitializer(List<SimpleApplicationEventMulticaster> eventMulticasters) {
    return () -> {
        for (SimpleApplicationEventMulticaster eventMulticaster : eventMulticasters) {
            //设置任务执行器 这样就实现了异步调用 (缺点是全局的,要么全异步,要么全同步,包括spring框架自身Listener)
            eventMulticaster.setTaskExecutor(Executors.newFixedThreadPool(10));
        }
    };
}

通过使用SmartInitializingSingleton,对现有的SimpleApplicationEventMulticaster进行增强。

SmartInitializingSingleton:

实现该接口后,当所有单例 bean 都初始化完成以后, 容器会回调该接口的方法 afterSingletonsInstantiated。主要应用场合就是在所有单例 bean 创建完成之后,可以在该回调中做一些事情。


以下这个方法会存在问题,导致自定义的Spring Boot事件监听不到,例如:ApplicationStartedEvent、ApplicationReadyEvent

我们看到AbstractApplicationContext类中如下代码,Spring会先获取已经存在的applicationEventMulticaster bean,没有的情况下才会重新创建一个。

APPLICATION_EVENT_MULTICASTER_BEAN_NAME="applicationEventMulticaster"

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
                    beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isDebugEnabled()) {
            logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    }
    else {
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isDebugEnabled()) {
            logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                    APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                    "': using default [" + this.applicationEventMulticaster + "]");
        }
    }
}

然后想到可以自定义一个ApplicationEventMulticaster bean,让系统使用我们的ApplicationEventMulticaster

@Bean
public ApplicationEventMulticaster applicationEventMulticaster(BeanFactory beanFactory) {
    SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
    eventMulticaster.setTaskExecutor(Executors.newFixedThreadPool(10));
    return eventMulticaster;
}

但是这种方式无法覆盖Spring Boot中的ApplicationEventMulticaster变量,由于Spring Boot中的此变量是new出来的

类:EventPublishingRunListener

private final ApplicationEventMulticaster multicaster;

public EventPublishingRunListener(SpringApplication application, String[] args) {
    ...
    // new一个出来
    this.multicaster = new SimpleApplicationEventMulticaster();
    ...
}

private void registerApplicationEventMulticaster(ConfigurableApplicationContext context) {
    // 注册到BeanFactory
    context.getBeanFactory().registerSingleton(
            AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME,
            this.multicaster);
    ...
}

private void publishEvent(SpringApplicationEvent event) {
    // 主要是这一行,Spring Boot直接使用内部变量发送事件
    this.multicaster.multicastEvent(event);
}

public void started() {
    // puublish ApplicationStartedEvent 事件
    publishEvent(new ApplicationStartedEvent(this.application, this.args));
}

其他方法:

使用:@EnableAsync与@Async注解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值