@Autowired -没有为依赖项找到类型的合格bean。

时间:2022-09-11 15:03:08

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的控制器,我可以在web浏览器中打开我的项目。

/src/main/resources/beans.xml

/ src / main /资源/它指明

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

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

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

. .不能自动连线:公共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?

我不该包含bean。xml在web。xml以某种方式?

12 个解决方案

#1


52  

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

您应该使用autowire接口AbstractManager而不是类邮件管理器。如果您有不同的AbstractManager实现,您可以编写@Component(“mailService”),然后将@Autowired @Qualifier(“mailService”)组合到autowire特定类中。

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

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

#2


18  

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 @ComponentScan in my test @Configuration class, so my tests weren't finding the components on which they relied.

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

So, double check that if you get this error.

再检查一下,如果你得到这个错误。

#3


8  

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

#4


3  

Spent much of my time with this! My bad! Later found that the class on which I declared the annotation Service or Component was 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.

我花了很多时间在这上面!我的坏!后来发现,我声明注释服务或组件的类是抽象的。在Springframework中启用了调试日志,但是没有收到提示。请检查类是否为抽象类。如果这样,应用的基本规则不能实例化一个抽象类。

#5


3  

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

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

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

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

#6


2  

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有一个隐藏import语句的选项,这就是为什么我一段时间没有看到它的原因。

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

我使用@org.jvnet.hk2.annotations。服务,而不是@org.springframework.stereotype.Service。

#7


1  

  • One reason BeanB may not exist in the context
  • BeanB可能不存在于上下文中的一个原因。
  • Another cause for the exception is the existence of two bean
  • 另一个例外的原因是两个bean的存在。
  • Or definitions in the context bean that isn’t defined is requested by name from the Spring context
  • 或者在上下文bean中定义的定义是由Spring上下文中的名称请求的。

see more this url:

看到更多的这个网址:

http://www.baeldung.com/spring-nosuchbeandefinitionexception

http://www.baeldung.com/spring-nosuchbeandefinitionexception

#8


0  

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

正如Max所建议的,正确的方法应该是autowire AbstractManager,但这也应该可以正常工作。

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

and

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

#9


0  

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-filter ="false"首先禁用的,然后只启用@Controller注释。因此,您的@Component注释没有启用。

#10


0  

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

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

#11


0  

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.

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

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

#12


0  

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

same issue arrived , i solved it by keeping the annotations intact and in dispatcher servlet :: keeping the base package scan as com.*. this worked for me.

同样的问题也来了,我通过在dispatcher servlet中保持注释的完整性来解决它::保持基本包扫描为com.*。这为我工作。

#1


52  

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

您应该使用autowire接口AbstractManager而不是类邮件管理器。如果您有不同的AbstractManager实现,您可以编写@Component(“mailService”),然后将@Autowired @Qualifier(“mailService”)组合到autowire特定类中。

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

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

#2


18  

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 @ComponentScan in my test @Configuration class, so my tests weren't finding the components on which they relied.

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

So, double check that if you get this error.

再检查一下,如果你得到这个错误。

#3


8  

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

#4


3  

Spent much of my time with this! My bad! Later found that the class on which I declared the annotation Service or Component was 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.

我花了很多时间在这上面!我的坏!后来发现,我声明注释服务或组件的类是抽象的。在Springframework中启用了调试日志,但是没有收到提示。请检查类是否为抽象类。如果这样,应用的基本规则不能实例化一个抽象类。

#5


3  

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

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

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

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

#6


2  

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有一个隐藏import语句的选项,这就是为什么我一段时间没有看到它的原因。

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

我使用@org.jvnet.hk2.annotations。服务,而不是@org.springframework.stereotype.Service。

#7


1  

  • One reason BeanB may not exist in the context
  • BeanB可能不存在于上下文中的一个原因。
  • Another cause for the exception is the existence of two bean
  • 另一个例外的原因是两个bean的存在。
  • Or definitions in the context bean that isn’t defined is requested by name from the Spring context
  • 或者在上下文bean中定义的定义是由Spring上下文中的名称请求的。

see more this url:

看到更多的这个网址:

http://www.baeldung.com/spring-nosuchbeandefinitionexception

http://www.baeldung.com/spring-nosuchbeandefinitionexception

#8


0  

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

正如Max所建议的,正确的方法应该是autowire AbstractManager,但这也应该可以正常工作。

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

and

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

#9


0  

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-filter ="false"首先禁用的,然后只启用@Controller注释。因此,您的@Component注释没有启用。

#10


0  

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

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

#11


0  

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.

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

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

#12


0  

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

same issue arrived , i solved it by keeping the annotations intact and in dispatcher servlet :: keeping the base package scan as com.*. this worked for me.

同样的问题也来了,我通过在dispatcher servlet中保持注释的完整性来解决它::保持基本包扫描为com.*。这为我工作。