@Async inside Runnable @Component class does not allow Autowired

I have two classes Uploader and UploadTask. Using Spring 4.

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

When the application starts, I get the following exception:

org.springframework.beans.factory.BeanCreationException: Error creating bean named 'uploader': injection of autodetected dependencies failed; The nested exception is org.springframework.beans.factory.BeanCreationException: Failed to create autwire field: private com.xx.uploading.UploadTask com.xx.uploading.Uploader.task; The nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: no qualified bean of type [com.xx.uploading.UploadTask] found for the dependency: at least 1 bean is expected that qualifies as an autwire candidate for this dependency. Dependency Annotations: {@ org.springframework.beans.factory.annotation.Autowired (required = true), @ org.springframework.beans.factory.annotation.Qualifier (value = uploadTask)}

I think it could be because UploadTask is Runnable. When I removed the @Async annotation, it does not throw an exception. Is there any explanation?

Update: When I saw the logs, I found that the UploadTask bean class is created in order. He is not at the time of the car industry.

+5
source share
4 answers

I have successfully run this code. see my code below.

  @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" /> 

Below is my test class

  @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"classpath*:/META-INF/spring/spring.xml"}) public class TestScope { @Autowired Uploader uploader = null; @Test public void testScope() { uploader.display(); } } 

Below is my 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> 

When I run the test class, it successfully prints sysout in UploadTask.

UPDATE I changed the encoding to run using @EnableAsync. See the modified code below.

Bootloader class

 @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 Interface

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

Class 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--"); } } 

All the rest are the same. This time I created UploaderTask as an interface and wrote a new class to implement it. This solves the problem.

I think @EnableAsync converts any component using @Async to a proxy server that implements the same interfaces used by this class of components, so when autwire with a particular class encounters a type conflict between this particular class and the proxy.

+1
source

Use @EnableAsync at the class level.

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

Create a public setter for the private task UploadTask; and test.

-1
source
 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. 
-1
source

Source: https://habr.com/ru/post/1242154/


All Articles