@Autowired-未找到依赖类型的合格bean


89

我通过使用Spring和Hibernate为服务创建实体,服务和JUnit测试来开始我的项目。所有这些都很好。然后,我添加了spring-mvc来使用许多不同的分步教程来制作此Web应用程序,但是当我尝试使用@Autowired注释制作Controller时,在部署过程中会从Glassfish中得到错误提示。我猜出于某种原因,Spring无法看到我的服务,但是经过多次尝试,我仍然无法处理它。

测试服务

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

@Autowired
MailManager mailManager;

正常工作。

也没有@Autowired的控制器,我可以在Web浏览器中打开项目而不会遇到麻烦。

/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";
    }

}

错误:

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)}

抱歉,有很多代码,但是我不知道是什么导致了该错误。

添加

我创建了界面:

@Component
public interface IMailManager {

添加的工具:

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

并更改为自动接线:

@Autowired
public IMailManager mailManager;

但是它仍然会引发错误(当我尝试使用@Qualifier时)

..无法自动连线栏位:public pl.com.radzikowski.webmail.service.IMailManager pl.com.radzikowski.webmail.controller.HomeController.mailManager ...

我也尝试了@Component和@Transactional的不同组合。

我是否应该以某种方式在web.xml中包含beans.xml?


您如何加载beans.xml?
Michael Wiles

现在如何只离开MailManagerInterface和之一IMailManager?:)
Patison

抱歉,我严重粘贴了代码。在我的程序中IMailManager无处不在。
Radzikowski

嗯,确切..添加<import resource="classpath:/beans.xml"/>mvc-dispatcher-servlet.xml
Patison

顺便说一句,您尝试过@emd决策吗?
Patison

Answers:


81

您应该自动连接接口AbstractManager而不是class MailManager。如果您有不同的实现,AbstractManager可以编写@Component("mailService")然后@Autowired @Qualifier("mailService")组合以自动装配特定的类。

这是由于Spring根据接口创建和使用代理对象。


2
谢谢,但仍然无法正常工作(相同错误)。我在帖子中添加了更改。也许我没有在项目中正确包含/搜索某些内容?
Radzikowski

我想知道是否有一种方法可以执行@Autowired AbstractManager[] abstractManagers包含其所有实现的操作。
WoLfPwNeR

@WoLfPwNeR它应该与您编写的完全一样。请参阅链接
-Patison

为什么不MailManager呢?
Alex78191 '18

我有两个@Service实现相同接口的类。两者都@Autowired在另一个班级。最初,当我使用特定的类类型时,它引起了与原始帖子相同的问题。按照此答案,我更改为使用接口类型和@Qualifier("myServiceA")@Qualifier("myServiceB"),并解决了问题。谢谢!
xialin

27

我发生这种情况是因为我的测试与我的组件不在同一个程序包中。(我重命名了我的组件包,但未重命名我的测试包。)而且我@ComponentScan在测试@Configuration类中使用,所以我的测试没有找到它们所依赖的组件。

因此,请仔细检查是否出现此错误。


2
这对我有用。当我将代码重构为新的程序包名称时,我的测试失败,因为我在@ComponentScan中使用了旧的程序包名称。
Vijay Vepakomma '16

1
如何使用in中的@Configuration类?src/mainsrc/test
Alex78191 '18

10

问题是在服务器启动期间,应用程序上下文和Web应用程序上下文都在WebApplicationContext中注册。运行测试时,必须明确告诉要加载的上下文。

试试这个:

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

1
如果正在使用Spring Boot,该怎么办?
Alex78191 '18

我忘了配置组件扫描以了解Maven依赖性,并且每年都要为此而苦苦挣扎。
b15

如果您是在谈论应用程序本身而不是集成测试,那么对于Spring boot,您可以这样操作: @SpringBootApplication(scanBasePackages = { "com.package.one", "com.package.two" })
b15

5

花了我很多时间!我的错!后来发现我在其上声明了注释ServiceComponent抽象的类。在Springframework上启用了调试日志,但未收到任何提示。请检查该类是否为抽象类型。如果这样,则应用的基本规则将无法实例化抽象类。


1
您救了我的先生,这很难被发现!
Japheth Ongeri-inkalimeva '18


3

从我的jar文件之一自动连接类时,我遇到了同样的问题。我通过使用@Lazy批注解决了该问题:

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

    @Autowired
    @Lazy
    private IGalaxyCommand iGalaxyCommand;


2

正确的方法应该是按照Max的建议自动连接AbstractManager,但这也可以正常工作。

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

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

2

我最近遇到了这个问题,事实证明,我在服务类中导入了错误的注释。Netbeans可以选择隐藏导入语句,这就是为什么我一段时间以来都没有看到它的原因。

我用@org.jvnet.hk2.annotations.Service代替@org.springframework.stereotype.Service



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

出现了同样的问题,我通过保持批注完整并在分派器servlet ::中解决了此问题,对基础包进行了扫描,因为com.*.这对我有用。


1

这可以帮助您:

我的项目中有同样的例外。搜索之后,我发现我在要实现@Autowired的接口的类中缺少@Service批注。

在您的代码中,您可以将@Service批注添加到MailManager类。

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

@Service注解包含@Component。两者都是多余的。
AnthonyW

1

您可以模拟如下所示的bean来代替@Autowire MailManager mailManager:

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

::
::

@MockBean MailManager mailManager;

另外,您可以配置 @MockBean MailManager mailManager;@SpringBootConfiguration类中分别进行和初始化,如下所示:

@Autowire MailManager mailManager

1

即使我启用了特定于软件包的扫描,在Spring Boot应用程序中也遇到了相同的问题,例如

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

但是,通过@ComponentScan({"com.*"})在我的Application类中提供,该问题得以解决。


0

我的猜测是

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

首先通过use-default-filters =“ false”禁用所有注释,然后仅启用@Controller注释。因此,您的@Component批注未启用。



0

之所以发生这种情况,是因为我在我的服务类中添加了自动关联,但是却忘记了将其添加到服务单元测试中的注入模拟中。

当问题实际上在单元测试中时,单元测试异常似乎报告了服务类中的问题。回想起来,错误消息告诉了我确切的问题所在。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.