Runnable @Component类中的@Async不允许它获得Autowired

时间:2016-02-03 05:58:35

标签: java spring spring-mvc

我有两个类Uploader和UploadTask。使用Spring 4.

 @Service 
 public class Uploader{
  @Autowired
  private UploadTask task;
 }
 @Component
 public class UploadTask implements Runnable{
   @Async
   public void soso(){
   }
   public void run(){
   }
 }

在应用程序启动时,我得到以下异常:

  

org.springframework.beans.factory.BeanCreationException:创建名为'uploader'的bean时出错:注入自动连接的依赖项失败;嵌套异常是org.springframework.beans.factory.BeanCreationException:无法自动装配字段:private com.xx.uploading.UploadTask com.xx.uploading.Uploader.task;嵌套异常是org.springframework.beans.factory.NoSuchBeanDefinitionException:没有为依赖项找到类型为[com.xx.uploading.UploadTask]的限定bean:期望至少有一个bean可以作为此依赖项的autowire候选者。依赖注释:{@ org.springframework.beans.factory.annotation.Autowired(required = true),@ org.springframework.beans.factory.annotation.Qualifier(value = uploadTask)}

我认为这可能是因为UploadTask是一个Runnable。当我删除@Async注释时,它不会抛出任何异常。有解释吗?

更新: 当我看到日志时,我发现正在创建UploadTask类bean。在自动装配期间没有找到它。

4 个答案:

答案 0 :(得分:1)

我已成功运行此代码。请参阅下面的代码。

     @Service 
 public class Uploader{
  @Autowired
  private UploadTask task;

  public void display(){
      task.run();
      task.soso();
  }
 }

 @Component
public class UploadTask implements Runnable{
  @Async
  public void soso(){
      System.out.println("Upload task running---");
  }
  public void run(){
      System.out.println("Running the class UploadTask---------");
  }
}

Spring.xml

  <mvc:annotation-driven/> 
    <context:component-scan base-package="com.exp" />

以下是我的测试类

    @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath*:/META-INF/spring/spring.xml"})
public class TestScope {

    @Autowired
    Uploader uploader = null;

    @Test
    public void testScope()
    {
        uploader.display();

    }
}

下面是我的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>SpringAsync-Exmp</groupId>
  <artifactId>SpringAsync-Exmp</artifactId>
  <version>0.0.1-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.2.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
            <scope>test</scope>
        </dependency>

       <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>   

当我运行测试类时,它成功在UploadTask中打印sysout。

<强>更新 我已修改编码以使用@EnableAsync运行。请在下面看到修改后的代码。

上传者课程

@EnableAsync
 @Service 
 public class Uploader{
  @Autowired
  private UploadTask uploadTask;


  public UploadTask getUploadTask() {
    return uploadTask;
}


public void setUploadTask(UploadTask uploadTask) {
    this.uploadTask = uploadTask;
}


public void display(){
      uploadTask.run();
      uploadTask.soso();
  }
 }

UploadTask接口

@Component
public interface UploadTask extends Runnable{
  @Async
  public void soso();
  public void run();
}

UploadTaskImpl类

public class UploadTaskImpl implements UploadTask{

      public void soso()
      {
          System.out.println("Inside the class----");
      }
      public void run()
      {
          System.out.println("Inside the class--run--");
      }
}

所有其他人都一样。这次我创建了UploaderTask作为接口并编写了一个新类来实现它。这解决了这个问题。

我认为@EnableAsync正在使用@Async将任何组件转换为代理实现此组件类使用的相同接口,因此当使用具体类进行autowire时,将面临此具体类与代理之间的类型冲突。

答案 1 :(得分:0)

在班级使用@EnableAsync。

@Component
@EnableAsync
public class UploadTask implements Runnable{
   @Async
   public void soso(){
   }
   public void run(){
   }
 }

答案 2 :(得分:-1)

拥有私有UploadTask任务的公共setter;并测试。

答案 3 :(得分:-1)

configure your service classes in the context.xml file.
like the below codes.

<bean id="Uploader" class="packageName.Uploader">
    <property name="task" ref="task"/>
</bean>

<bean id="task" class="packageName.UploadTask ">
    <property name="xxx" ref="xxx"/>
</bean>
change xxx with your datasource name.