2016-02-03 4 views
5

Ich habe zwei Klassen Uploader und UploadTask. Mit Spring 4.@Async innerhalb einer Runnable @ Component-Klasse wird nicht lassen Sie Autowired

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

beim Anwendungsstart erhalte ich die folgende Ausnahme:

org.springframework.beans.factory.BeanCreationException: Fehler beim Erstellen der Bohne mit dem Namen 'Uploader': Die Injektion von autowired Abhängigkeiten fehlgeschlagen ; verschachtelte Ausnahme ist org.springframework.beans.factory.BeanCreationException: Feld konnte nicht automatisch gestartet werden: private com.xx.uploading.UploadTask com.xx.uploading.Uploader.task; verschachtelte Ausnahme ist org.springframework.beans.factory.NoSuchBeanDefinitionException: Kein qualifizierendes Bean vom Typ [com.xx.uploading.UploadTask] gefunden für Abhängigkeit: erwartet mindestens 1 Bean, das sich als Autowire-Kandidat für diese Abhängigkeit qualifiziert. Dependency Anmerkungen: {@ org.springframework.beans.factory.annotation.Autowired (required = true), @ org.springframework.beans.factory.annotation.Qualifier (Wert = uploadTask)}

ich denke, das kann weil UploadTask eine ausführbare Datei ist. Wenn ich die @ Async-Annotation entfernt habe, wird keine Ausnahme ausgelöst. Gibt es eine Erklärung?

Update: Als ich die Protokolle sah, fand ich, dass die UploadTask-Klasse Bean in Ordnung ist. Es wird nicht während des Autowiderlaufs gefunden.

+1

'@ Async' erfordert die Erstellung eines Proxys und abhängig von Ihrer Konfiguration ist der Proxy vom Typ' Runnable'. – zeroflagL

+0

Gibt es also keine Möglichkeit, eine Async-Methode in einem Runnable zu erstellen? – zafar142003

+0

Entweder eine 'UploadTask'-Schnittstelle zuerst erstellen und von der Komponente implementieren lassen oder die Proxy-Konfiguration in Ihrer Spring-Konfiguration ändern. Angenommen, das ist natürlich das Problem. – zeroflagL

Antwort

-1

Einen öffentlichen Setter für private UploadTask Aufgabe haben; und testen.

+0

Ich habe erwähnt, dass das Entfernen von @ Async das Problem löst. Daher ist es kein Problem eines öffentlichen Settlers. – zafar142003

0

Verwenden Sie @EnableAsync auf Klassenebene.

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

@EnableAsync hilft nicht. Anyway hatte ich schon in die context-Datei geschrieben. Also macht diese Anmerkung nichts extra. – zafar142003

-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. 
+0

Dies ist redundant. Anmerkungen tun dies. – zafar142003

1

Ich habe diesen Code erfolgreich ausgeführt werden. Bitte beachten Sie meinen Code unten.

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

Unten finden Sie meine Testklasse

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

    @Autowired 
    Uploader uploader = null; 

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

    } 
} 

Unten ist mein 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> 

Wenn ich die Testklasse laufen, es Drucken Sie den SYSOUT in UploadTask erfolgreich.

AKTUALISIEREN Ich habe den Code so geändert, dass er mit @EnableAsync läuft. Bitte sehen Sie unten den geänderten Code.

Uploader Klasse

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

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

UploadTaskImpl Klasse

public class UploadTaskImpl implements UploadTask{ 

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

Alle anderen sind gleich. Dieses Mal habe ich UploaderTask als Schnittstelle erstellt und schreibe eine neue Klasse, um das zu implementieren. Dies löst das Problem.

Ich glaube, @EnableAsync konvertiert jede Komponente mit @ Async zu Proxy-Implementierung der gleichen Schnittstellen von dieser Komponente-Klasse verwendet, so wenn Sie Autowire mit konkreten Klasse Typ Konflikt zwischen dieser konkreten Klasse und Proxy konfrontiert werden.

+0

Ich sehe keine spezielle Ergänzung in Ihrer Antwort. Was soll ich tun, damit mein Fall funktioniert? Außerdem haben Sie weder @EnableAsync in Ihrer Klasse noch in Ihrem Kontext. Ihr Fall sollte nicht ohne das laufen. – zafar142003

+0

Ich habe die Antwort modifiziert, um Ihre Anforderung zu erfüllen. Bitte kommentieren Sie, ob es für Sie funktioniert oder nicht. –

+0

Sorry, aber das funktioniert auch nicht. – zafar142003

Verwandte Themen