@Autowired - Keine qualifizierende Bean vom Typ für Abhängigkeit gefunden


86

Ich habe mein Projekt mit dem Erstellen von Entitäten, Diensten und JUnit-Tests für Dienste mit Spring und Hibernate begonnen. All dies funktioniert großartig. Dann habe ich spring-mvc hinzugefügt, um diese Webanwendung mit vielen verschiedenen Schritt-für-Schritt-Anleitungen zu erstellen. Wenn ich jedoch versuche, Controller mit @ Autowired-Annotation zu erstellen, werden während der Bereitstellung Fehler von Glassfish angezeigt. Ich denke, dass Spring aus irgendeinem Grund meine Dienste nicht sieht, aber nach vielen Versuchen kann ich immer noch nicht damit umgehen.

Tests für Dienste mit

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/beans.xml"})

und

@Autowired
MailManager mailManager;

Funktioniert einwandfrei.

Controller auch ohne @Autowired kann ich mein Projekt problemlos im Webbrowser öffnen.

/src/main/resources/beans.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
        http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd">

    <context:property-placeholder location="jdbc.properties" />

    <context:component-scan base-package="pl.com.radzikowski.webmail">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

    <!--<context:component-scan base-package="pl.com.radzikowski.webmail.service" />-->

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>

    <!-- Persistance Unit Manager for persistance options managing -->
    <bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
        <property name="defaultDataSource" ref="dataSource"/>
    </bean>

    <!-- Entity Manager Factory for creating/updating DB schema based on persistence files and entity classes -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitManager" ref="persistenceUnitManager"/>
        <property name="persistenceUnitName" value="WebMailPU"/>
    </bean>

    <!-- Hibernate Session Factory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--<property name="schemaUpdate" value="true" />-->
        <property name="packagesToScan" value="pl.com.radzikowski.webmail.domain" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            </props>
        </property>
    </bean>

    <!-- Hibernate Transaction Manager -->
    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!-- Activates annotation based transaction management -->
    <tx:annotation-driven transaction-manager="txManager"/>

</beans>

/webapp/WEB-INF/web.xml

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="WebApp_ID" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>Spring Web MVC Application</display-name>
    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

/webapp/WEB-INF/mvc-dispatcher-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <context:component-scan base-package="pl.com.radzikowski.webmail" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

    <mvc:annotation-driven/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>

</beans>

pl.com.radzikowski.webmail.service.AbstractManager

package pl.com.radzikowski.webmail.service;

import org.apache.log4j.Logger;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * Master Manager class providing basic fields for services.
 * @author Maciej Radzikowski <maciej@radzikowski.com.pl>
 */
public class AbstractManager {

    @Autowired
    protected SessionFactory sessionFactory;

    protected final Logger logger = Logger.getLogger(this.getClass());

}

pl.com.radzikowski.webmail.service.MailManager

package pl.com.radzikowski.webmail.service;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
@Transactional
public class MailManager extends AbstractManager {
    // some methods...
}

pl.com.radzikowski.webmail.HomeController

package pl.com.radzikowski.webmail.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import pl.com.radzikowski.webmail.service.MailManager;

@Controller
@RequestMapping("/")
public class HomeController {

    @Autowired
    public MailManager mailManager;

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String homepage(ModelMap model) {
        return "homepage";
    }

}

Error:

SEVERE:   Exception while loading the app
SEVERE:   Undeployment failed for context /WebMail
SEVERE:   Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public pl.com.radzikowski.webmail.service.MailManager pl.com.radzikowski.webmail.controller.HomeController.mailManager; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [pl.com.radzikowski.webmail.service.MailManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Entschuldigung für viel Code, aber ich weiß nicht mehr, was diesen Fehler verursachen kann.

Hinzugefügt

Ich habe die Schnittstelle erstellt:

@Component
public interface IMailManager {

Geräte hinzugefügt:

@Component
@Transactional
public class MailManager extends AbstractManager implements IMailManager {

und automatisch verdrahtet geändert:

@Autowired
public IMailManager mailManager;

Aber es gibt immer noch Fehler (auch wenn ich es mit @Qualifier versucht habe)

..Kann nicht automatisch verdrahtet werden: public pl.com.radzikowski.webmail.service.IMailManager pl.com.radzikowski.webmail.controller.HomeController.mailManager ...

Ich habe es auch mit verschiedenen Kombinationen von @Component und @Transactional versucht.

Sollte ich beans.xml nicht irgendwie in web.xml aufnehmen?


Wie lädst du beans.xml?
Michael Wiles

Wie wäre es nun, nur eines von MailManagerInterfaceund zu verlassen IMailManager? :)
Patison

Entschuldigung, ich habe den Code schlecht eingefügt. In meinem Programm gibt es IMailManagerüberall.
Radzikowski

ah, genau .. hinzufügen <import resource="classpath:/beans.xml"/>zumvc-dispatcher-servlet.xml
Patison

Haben Sie übrigens die Entscheidung @emd ausprobiert?
Patison

Antworten:


79

Sie sollten die Autowire-Schnittstelle AbstractManageranstelle der Klasse verwenden MailManager. Wenn Sie unterschiedliche Implementierungen haben AbstractManager, können Sie schreiben @Component("mailService")und dann @Autowired @Qualifier("mailService")kombinieren, um eine bestimmte Klasse automatisch zu verdrahten.

Dies liegt an der Tatsache, dass Spring Proxy-Objekte basierend auf den Schnittstellen erstellt und verwendet.


2
Danke, aber es funktioniert immer noch nicht (gleicher Fehler). Ich habe Änderungen in der Post hinzugefügt. Vielleicht habe ich etwas in meinem Projekt nicht richtig aufgenommen / gesucht?
Radzikowski

Ich frage mich, ob es eine Möglichkeit gibt, so etwas zu tun @Autowired AbstractManager[] abstractManagers, das alle seine Implementierungen enthält.
WoLfPwNeR

@WoLfPwNeR Es sollte genau so funktionieren, wie Sie es geschrieben haben. Siehe Link
Patison

Warum nicht MailManager?
Alex78191

Ich habe zwei @ServiceKlassen, die dieselbe Schnittstelle implementieren. Beide sind @Autowiredin einer anderen Klasse. Anfangs verursachte es das gleiche Problem wie der ursprüngliche Beitrag, als ich den spezifischen Klassentyp verwendete. Nach dieser Antwort habe ich den Schnittstellentyp mit einem anderen @Qualifier("myServiceA")und verwendet @Qualifier("myServiceB")und das Problem wurde behoben. Vielen Dank!
Xialin

26

Ich hatte dies geschehen, weil meine Tests nicht im selben Paket wie meine Komponenten waren. (Ich hatte mein Komponentenpaket umbenannt, aber nicht mein Testpaket.) Und ich habe es @ComponentScanin meinem Test verwendet@Configuration , sodass meine Tests nicht die Komponenten fanden, auf die sie sich stützten.

Überprüfen Sie dies, wenn Sie diesen Fehler erhalten.


1
Das hat bei mir funktioniert. Meine Tests sind fehlgeschlagen, als ich den Code überarbeitet habe, um zu einem neuen Paketnamen zu wechseln, da ich den alten Paketnamen in @ComponentScan verwendet habe.
Vijay Vepakomma

1
Wie benutzt man @ConfigurationKlasse von src/mainin src/test?
Alex78191

9

Die Sache ist, dass sowohl der Anwendungskontext als auch der Webanwendungskontext während des Serverstarts im WebApplicationContext registriert werden. Wenn Sie den Test ausführen, müssen Sie explizit angeben, welche Kontexte geladen werden sollen.

Versuche dies:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/beans.xml", "/mvc-dispatcher-servlet.xml"})

Wie mache ich das, wenn ich Spring Boot benutze?
Alex78191

5

Ich habe viel Zeit damit verbracht! Mein Fehler! Später stellte ich fest, dass die Klasse, für die ich die Anmerkung deklarierte Serviceoder Componentvom Typ abstrakt war. Hatte Debug-Protokolle in Springframework aktiviert, aber es wurde kein Hinweis empfangen. Bitte überprüfen Sie, ob die Klasse vom abstrakten Typ ist. Wenn dann die angewandte Grundregel eine abstrakte Klasse nicht instanziieren kann.


1
Sie haben meinen Tag gerettet, Sir, das ist so schwer zu erkennen!
Japheth Ongeri - Inkalimeva


3

Ich hatte das gleiche Problem, als ich die Klasse automatisch aus einer meiner JAR-Dateien verdrahtete. Ich habe das Problem mithilfe der @ Lazy-Annotation behoben:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

    @Autowired
    @Lazy
    private IGalaxyCommand iGalaxyCommand;

2

Der richtige Weg sollte sein, AbstractManager automatisch zu verdrahten, wie Max vorgeschlagen hat, aber dies sollte auch gut funktionieren.

@Autowired
@Qualifier(value="mailService")
public MailManager mailManager;

und

@Component("mailService")
@Transactional
public class MailManager extends AbstractManager {
}

2

Ich bin kürzlich darauf gestoßen, und wie sich herausstellte, habe ich die falsche Anmerkung in meine Serviceklasse importiert. Netbeans hat die Option, Importanweisungen auszublenden. Deshalb habe ich sie einige Zeit nicht gesehen.

Ich habe verwendet @org.jvnet.hk2.annotations.Servicestatt @org.springframework.stereotype.Service.



1
 <context:component-scan base-package="com.*" />

Das gleiche Problem ist aufgetreten. Ich habe es gelöst, indem ich die Anmerkungen intakt gehalten und im Dispatcher- Servlet :: den Basispaket-Scan beibehalten habe, da com.*.dies für mich funktioniert hat.


1

Dies kann Ihnen helfen:

Ich habe die gleiche Ausnahme in meinem Projekt. Nach der Suche habe ich festgestellt, dass mir die Annotation @Service für die Klasse fehlt, in der ich die Schnittstelle implementiere, die ich @Autowired verwenden möchte.

In Ihrem Code können Sie die Annotation @Service zur MailManager-Klasse hinzufügen.

@Transactional
@Service
public class MailManager extends AbstractManager implements IMailManager {

Die @ServiceAnmerkung enthält @Component. Beides zu haben ist überflüssig.
AnthonyW

1

Anstelle von @Autowire MailManager mailManager können Sie die Bean wie folgt verspotten:

import org.springframework.boot.test.mock.mockito.MockBean;

::
::

@MockBean MailManager mailManager;

Sie können @MockBean MailManager mailManager;die @SpringBootConfigurationKlasse auch separat konfigurieren und wie folgt initialisieren:

@Autowire MailManager mailManager

0

Ich vermute, das hier

<context:component-scan base-package="pl.com.radzikowski.webmail" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

Alle Annotationen werden zuerst durch use-default-filter = "false" deaktiviert und dann nur die @ Controller-Annotation aktiviert. Daher ist Ihre @ Component-Annotation nicht aktiviert.


0

Wenn Sie Ihren Controller testen. Vergessen Sie nicht, @WebAppConfiguration für Ihre Testklasse zu verwenden.


0

Dies geschah, weil ich meiner Serviceklasse eine automatisch verdrahtete Abhängigkeit hinzugefügt habe, aber vergessen habe, sie in meinem Serviceeinheitentest zu den injizierten Mocks hinzuzufügen.

Die Unit-Test-Ausnahme schien ein Problem in der Serviceklasse zu melden, als das Problem tatsächlich im Unit-Test lag. Rückblickend sagte mir die Fehlermeldung genau, was das Problem war.


0

Das gleiche Problem trat in meiner Spring-Boot-Anwendung auf, obwohl ich meine paketspezifischen Scans wie aktiviert hatte

@SpringBootApplication(scanBasePackages={"com.*"})

Das Problem wurde jedoch durch Angabe @ComponentScan({"com.*"})in meiner Anwendungsklasse behoben .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.