it-roy-ru.com

@Autowired - не найден подходящий компонент типа для зависимости

Я начал свой проект с создания сущностей, сервисов и тестов JUnit для сервисов с использованием Spring и Hibernate. Все это прекрасно работает . Затем я добавил spring-mvc, чтобы сделать это веб-приложение с помощью множества различных пошаговых руководств, но когда я пытаюсь создать Controller с аннотацией @Autowired, я получаю ошибки Glassfish при развертывании. Я думаю, что по какой-то причине Spring не видит моих услуг, но после многих попыток я все еще не могу справиться с этим.

Тесты на услуги с 

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

а также

@Autowired
MailManager mailManager;

работает правильно.

Контроллеры без @Autowired тоже, я могу без проблем открыть свой проект в веб-браузере.

/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 <[email protected]>
 */
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 тоже.

Разве я не должен как-то включать beans.xml в web.xml?

65
Radzikowski

Вы должны автоматически подключить интерфейс AbstractManager вместо класса MailManager. Если у вас есть разные реализации AbstractManager, вы можете написать комбинацию @Component("mailService"), а затем @Autowired @Qualifier("mailService") для автоматического связывания определенного класса.

Это связано с тем, что Spring создает и использует прокси-объекты на основе интерфейсов.

58
Patison

Это произошло потому, что мои тесты не были в той же упаковке, что и мои компоненты. (Я переименовал свой пакет компонентов, но не мой тестовый пакет.) И я использовал @ComponentScan в своем тестовом классе @Configuration, поэтому мои тесты не находили компоненты, на которые они опирались.

Итак, дважды проверьте это, если вы получаете эту ошибку.

22
mooreds

Дело в том, что и контекст приложения, и контекст веб-приложения регистрируются в WebApplicationContext при запуске сервера. Когда вы запускаете тест, вы должны явно указать, какие контексты загружать. 

Попробуй это:

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

Потратил много времени с этим! Виноват! Позже выяснилось, что класс, для которого я объявил аннотацию Service или Component, был типа abstract. Включил журналы отладки на Springframework, но подсказка не была получена. Пожалуйста, проверьте, если класс, если абстрактного типа. Если тогда, основное правило применяется, не может создать экземпляр абстрактного класса.

5
James Jithin

Правильный путь должен состоять в том, чтобы автоматически связать AbstractManager, как предположил Макс, но это также должно работать нормально.

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

а также

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

Можете ли вы попробовать аннотировать только вашу конкретную реализацию с помощью @Component? Может быть, следующий ответ мог бы помочь. Это отчасти похожая проблема. Я обычно помещаю аннотации Spring в классы реализации.

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

3
whyem

Я столкнулся с этим недавно, и, как оказалось, я импортировал неправильную аннотацию в своем классе обслуживания. Netbeans имеет возможность скрыть операторы импорта, поэтому я некоторое время не видел его.

Я использовал @org.jvnet.hk2.annotations.Service вместо @org.springframework.stereotype.Service.

2
kazmer

Это может помочь вам:

У меня такое же исключение в моем проекте. После поиска я обнаружил, что мне не хватает аннотации @Service в классе, где я реализую интерфейс, который я хочу @Autowired.

В своем коде вы можете добавить аннотацию @Service к классу MailManager.

@Transactional
@Service
public class MailManager extends AbstractManager implements IMailManager {
1
Akshay Pethani
  • Одна из причин, по которой BeanB может не существовать в контексте 
  • Еще одной причиной для исключения является наличие двух бобов
  • Или определения в bean-компоненте контекста, который не определен, запрашиваются по имени из контекста Spring.

увидеть больше этот URL:

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

1
zohreh

Я думаю, что здесь

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

Вместо @Autowire MailManager mailManager вы можете смоделировать bean-компонент, как показано ниже:

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

::
::

@MockBean MailManager mailManager;

Кроме того, вы можете настроить @MockBean MailManager mailManager; отдельно в классе @SpringBootConfiguration и инициализировать, как показано ниже:

@Autowire MailManager mailManager
0
Barani r

Я столкнулся с той же проблемой при автоматическом подключении класса к одному из моих jar-файлов .... Я исправил проблему с помощью аннотации @Lazy:

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

    @Autowired
    @Lazy
    private IGalaxyCommand iGalaxyCommand;

0
Ved Singh

Если вы тестируете свой контроллер . Не забудьте использовать @WebAppConfiguration в вашем тестовом классе.

0
Joao Luiz Cadore

Это произошло из-за того, что я добавил в свой класс обслуживания автоматическую зависимость, но забыл добавить ее к внедренным макетам в моем тесте модуля обслуживания.

Исключение модульного теста, по-видимому, сообщает о проблеме в классе обслуживания, когда проблема была на самом деле в модульном тесте. В ретроспективе, сообщение об ошибке говорит мне точно, в чем проблема.

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

пришла та же проблема, я решил ее, сохранив аннотации в неизменном виде и в диспетчере servlet :: сохранив сканирование базового пакета, так как com.*. у меня сработало. 

0
Ramanpreet Singh