Java @Autowired - 没有为依赖找到符合条件的 bean

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20333147/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 01:08:37  来源:igfitidea点击:

@Autowired - No qualifying bean of type found for dependency

javaspringspring-mvcannotationsautowired

提问by Radzikowski

I've started my project by creating entities, services and JUnit tests for services using Spring and Hibernate. All of this works great. Then I've added spring-mvc to make this web application using many different step-by-step tutorials, but when I'm trying to make Controller with @Autowired annotation, I'm getting errors from Glassfish during deployment. I guess that for some reason Spring doesn't see my services, but after many attempts I still can't handle it.

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

Tests for services with

测试服务

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

and

@Autowired
MailManager mailManager;

works properly.

工作正常。

Controllers without @Autowired too, I can open my project in web browser without trouble.

也没有@Autowired 的控制器,我可以毫无困难地在网络浏览器中打开我的项目。

/src/main/resources/beans.xml

/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

/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

/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

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 <[email protected]>
 */
public class AbstractManager {

    @Autowired
    protected SessionFactory sessionFactory;

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

}

pl.com.radzikowski.webmail.service.MailManager

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

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

Sorry for a lot of code, but I don't know what can cause that error anymore.

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

Added

添加

I've created the interface:

我已经创建了界面:

@Component
public interface IMailManager {

added implements:

添加工具:

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

and changed autowired:

并更改了自动装配:

@Autowired
public IMailManager mailManager;

But it still throws errors (also when I've tried with @Qualifier)

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

..Could not autowire field: public pl.com.radzikowski.webmail.service.IMailManager pl.com.radzikowski.webmail.controller.HomeController.mailManager...

..无法自动装配字段:public pl.com.radzikowski.webmail.service.IMailManager pl.com.radzikowski.webmail.controller.HomeController.mailManager...

I've tried with different combinations of @Component and @Transactional too.

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

Shouldn't I include beans.xml in web.xml somehow?

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

采纳答案by Patison

You should autowire interface AbstractManagerinstead of class MailManager. If you have different implemetations of AbstractManageryou can write @Component("mailService")and then @Autowired @Qualifier("mailService")combination to autowire specific class.

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

This is due to the fact that Spring creates and uses proxy objects based on the interfaces.

这是因为 Spring 基于接口创建和使用代理对象。

回答by emd

The thing is that both the application context and the web application context are registered in the WebApplicationContext during server startup. When you run the test you must explicitly tell which contexts to load.

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

Try this:

尝试这个:

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

回答by Abhishek Anand

Correct way shall be to autowire AbstractManager, as Max suggested, but this should work fine as well.

正确的方法应该是自动装配 AbstractManager,正如 Max 建议的那样,但这也应该可以正常工作。

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

and

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

回答by whyem

Can you try annotating only your concrete implementation with @Component? Maybe the following answercould help. It is kind of a similar problem. I usually put Spring annotations in the implementation classes.

您可以尝试仅使用 注释您的具体实现@Component吗?也许以下答案会有所帮助。这是一个类似的问题。我通常将 Spring 注解放在实现类中。

https://stackoverflow.com/a/10322456/2619091

https://stackoverflow.com/a/10322456/2619091

回答by James Jithin

Spent much of my time with this! My bad! Later found that the class on which I declared the annotation Serviceor Componentwas of type abstract. Had enabled debug logs on Springframework but no hint was received. Please check if the class if of abstract type. If then, the basic rule applied, can't instantiate an abstract class.

我花了很多时间在这上面!我的错!后来发现我声明注解的类Service或者Component是抽象类型。已在 Springframework 上启用调试日志,但未收到任何提示。请检查该类是否为抽象类型。如果那样的话,应用的基本规则就不能实例化一个抽象类。

回答by mooreds

I had this happen because my tests were not in the same package as my components. (I had renamed my component package, but not my test package.) And I was using @ComponentScanin my test @Configurationclass, so my tests weren't finding the components on which they relied.

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

So, double check that if you get this error.

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

回答by LoBo

My guess is that here

我的猜测是这里

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

all annotations are first disabled by use-default-filters="false" and then only @Controller annotation enabled. Thus, your @Component annotation is not enabled.

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

回答by kazmer

I ran in to this recently, and as it turned out, I've imported the wrong annotation in my service class. Netbeans has an option to hide import statements, that's why I did not see it for some time.

我最近遇到了这个问题,结果证明我在我的服务类中导入了错误的注释。Netbeans 有一个隐藏导入语句的选项,这就是为什么我有一段时间没有看到它。

I've used @org.jvnet.hk2.annotations.Serviceinstead of @org.springframework.stereotype.Service.

我用过@org.jvnet.hk2.annotations.Service而不是@org.springframework.stereotype.Service.

回答by Joao Luiz Cadore

If you are testing your controller. Don't forget to use @WebAppConfiguration on your test class.

如果您正在测试您的控制器。不要忘记在您的测试类上使用 @WebAppConfiguration。

回答by Akshay Pethani

This may help you:

这可能会帮助您:

I have the same exception in my project. After searching while I found that I am missing the @Service annotation to the class where I am implementing the interface which I want to @Autowired.

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

In your code you can add the @Service annotation to MailManager class.

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

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