简体   繁体   English

升级到Spring Boot 1.3.3后,@ Async无法正常工作

[英]@Async not working after upgrading to Spring Boot 1.3.3

I have an application running under Spring Boot 1.2.3 that uses methods annotated with @Async . 我有一个在Spring Boot 1.2.3下运行的应用程序,它使用@Async注释的方法。 To date it's been working properly. 到目前为止,它一直在正常工作。

After upgrading to Spring Boot 1.3.3, methods marked as @Async are not being called in a separate thread. 升级到Spring Boot 1.3.3后,标记为@Async方法不会在单独的线程中调用。

Here's a sample program that illustrates the issue: 这是一个说明问题的示例程序:

App.java: App.java:

package test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;


@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackages = { "test" })
@EnableAsync
public class App implements CommandLineRunner {

    private static final Logger log = LoggerFactory.getLogger(App.class);

    @Autowired
    AsyncClass async;

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

    public void run(String... arg0) throws Exception {
        log.info("in run");
        async.start();
        log.info("done run");
    }

}

AsyncClass.java: AsyncClass.java:

package test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;


@Component
public class AsyncClass {

    private static final Logger log = LoggerFactory.getLogger(AsyncClass.class);

    @Async("myTaskExecutor")
    public void start() {
        log.info("in async task");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) { }
        log.info("done async task");
    }

    @Bean
    public ThreadPoolTaskExecutor myTaskExecutor() {

        ThreadPoolTaskExecutor bean = new ThreadPoolTaskExecutor();
        bean.setCorePoolSize(1);
        bean.setMaxPoolSize(1);
        bean.setQueueCapacity(10);
        bean.setThreadPriority(1);
        bean.setWaitForTasksToCompleteOnShutdown(true);
        return bean;
    }

}

pom.xml: pom.xml中:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>dbush</groupId>
  <artifactId>async-test</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>async-test</name>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>      
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <!-- this is the only line that differs -->
        <version>1.3.3.RELEASE</version>
    </parent>

  <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>log4j-over-slf4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

</project>

Under 1.2.3, the log statements in the start method show them as running in thread myTaskExecutor-1 . 在1.2.3下, start方法中的日志语句将它们显示为在线程myTaskExecutor-1运行。 Under 1.3.3, the same logs show that they run in thread main . 在1.3.3下,相同的日志显示它们在main线程中运行。

Any idea what might be wrong here? 知道这里可能有什么问题吗?

You need place your bean factory method in a other class annotated as @Configuration. 您需要将bean工厂方法放在另一个注释为@Configuration的类中。 Executor will be used for @Async method execution in this way. Executor将以这种方式用于@Async方法执行。

@Configuration
@EnableAsync
public class AsyncConfig {
   @Bean(name = "myTaskExecutor")
   public ThreadPoolTaskExecutor myTaskExecutor() {
      return new ThreadPoolTaskExecutor();
   }
}

Injecting into configuration classes might be a challenge, I wouldn't recommend it especially if that class is also an actual bean. 注入配置类可能是一个挑战,我不推荐它,特别是如果该类也是一个实际的bean。 IMHO your class does too much. 恕我直言,你的班级做得太多了。 Next to that move the configuration of the ThreadPoolTaskExecutor where it belongs. 接下来移动它所属的ThreadPoolTaskExecutor的配置。

Instead of autowiring create a @Bean method which returns a CommandLineRunner instead of you implementing it. 而不是自动装配创建一个返回CommandLineRunner而不是实现它的@Bean方法。

@SpringBootApplication
@EnableAsync
public class App {

    private static final Logger log = LoggerFactory.getLogger(App.class);

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

    @Bean
    public CommandLineRunner runner(AsyncClass async) {

      return new CommandLineRunner() {
        public void run(String... arg0) throws Exception {
            log.info("in run");
            async.start();
            log.info("done run");
        }      
      };

    }

    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {

        ThreadPoolTaskExecutor bean = new ThreadPoolTaskExecutor();
        bean.setCorePoolSize(1);
        bean.setMaxPoolSize(1);
        bean.setQueueCapacity(10);
        bean.setThreadPriority(1);
        bean.setWaitForTasksToCompleteOnShutdown(true);
        return bean;
    }
}

And of course cleanup your AsyncClass . 当然要清理你的AsyncClass

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM