@Autowired-종속성에 대한 유형의 한정 빈이 없습니다.


89

Spring과 Hibernate를 사용하는 서비스에 대한 엔티티, 서비스 및 JUnit 테스트를 생성하여 프로젝트를 시작했습니다. 이 모든 것이 훌륭하게 작동합니다. 그런 다음 다양한 단계별 자습서를 사용하여이 웹 응용 프로그램을 만들기 위해 spring-mvc를 추가했지만 @Autowired 주석으로 Controller를 만들려고 할 때 배포 중에 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 <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 :

@Autowired
public IMailManager mailManager;

하지만 여전히 오류가 발생합니다 (@Qualifier로 시도했을 때도)

..Could not autowire field : 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 2013

죄송합니다. 코드를 잘못 붙여 넣었습니다. 내 프로그램에는 IMailManager어디에나 있습니다.
Radzikowski 2013

아, 정확히 .. 추가 <import resource="classpath:/beans.xml"/>mvc-dispatcher-servlet.xml
Patison

그건 그렇고, @emd 결정을 시도 했습니까?
Patison 2013-12-02

답변:


81

AbstractManagerclass 대신 인터페이스 를 자동 연결 해야합니다 MailManager. 다른 구현이 있다면 AbstractManager작성 @Component("mailService")하고 @Autowired @Qualifier("mailService")조합하여 특정 클래스를 autowire 할 수 있습니다 .

이는 Spring이 인터페이스를 기반으로 프록시 객체를 생성하고 사용하기 때문입니다.


2
감사하지만 여전히 작동하지 않습니다 (동일한 오류). 게시물에 변경 사항을 추가했습니다. 프로젝트에 제대로 포함 / 검색하지 않았을까요?
Radzikowski

@Autowired AbstractManager[] abstractManagers모든 구현을 포함 하는 것과 같은 작업을 수행하는 방법이 있는지 궁금합니다 .
WoLfPwNeR

@WoLfPwNeR 작성하신대로 정확하게 작동합니다. 참조 링크
Patison

왜 안돼 MailManager?
Alex78191

@Service동일한 인터페이스를 구현하는 두 개의 클래스가 있습니다. 둘 다 @Autowired다른 클래스에 있습니다. 처음에는 특정 클래스 유형을 사용할 때 원래 게시물과 동일한 문제가 발생했습니다. 이 답변에 따라 @Qualifier("myServiceA")및 다른 인터페이스 유형을 사용하도록 변경 @Qualifier("myServiceB")했으며 문제가 해결되었습니다. 감사!
xialin

27

내 테스트가 내 구성 요소와 동일한 패키지에 없기 때문에 이런 일이 발생했습니다. (내 구성 요소 패키지의 이름은 변경했지만 테스트 패키지는 변경하지 않았습니다.) @ComponentScan테스트 @Configuration클래스 에서 사용 하고 있었기 때문에 테스트에서 신뢰할 수있는 구성 요소를 찾지 못했습니다.

따라서이 오류가 발생하면 다시 확인하십시오.


2
이것은 나를 위해 일했습니다. @ComponentScan에서 이전 패키지 이름을 사용했기 때문에 새 패키지 이름으로 이동하도록 코드를 리팩터링 할 때 테스트가 실패했습니다.
Vijay Vepakomma

1
in에서 @Configuration클래스 를 사용하는 방법 ? src/mainsrc/test
Alex78191

10

문제는 응용 프로그램 컨텍스트와 웹 응용 프로그램 컨텍스트가 모두 서버 시작 중에 WebApplicationContext에 등록된다는 것입니다. 테스트를 실행할 때로드 할 컨텍스트를 명시 적으로 지정해야합니다.

이 시도:

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

1
Spring Boot를 사용하는 경우 어떻게해야합니까?
Alex78191

Maven 종속성에 대한 구성 요소 스캔을 구성하는 것을 잊고 일년에 한 번 이와 같이 고생합니다.
b15

통합 테스트가 아닌 애플리케이션 자체에 대해 이야기하고 있다면 Spring 부트의 경우 다음과 같이 할 수 있습니다. @SpringBootApplication(scanBasePackages = { "com.package.one", "com.package.two" })
b15

5

이것으로 많은 시간을 보냈습니다! 내 잘못이야! 나중에 내가 주석을 선언 Service했거나 Component추상 유형 인 클래스를 발견했습니다 . Springframework에서 디버그 로그를 활성화했지만 힌트를받지 못했습니다. 클래스가 추상 유형인지 확인하십시오. 그렇다면 적용된 기본 규칙은 추상 클래스를 인스턴스화 할 수 없습니다.


1
제 하루를 구해 주셨습니다. 감지하기가 너무 어렵습니다!
야벳 Ongeri - inkalimeva

4

내 jar 파일 중 하나에서 클래스를 자동 연결하는 동안 동일한 문제에 직면했습니다. @Lazy 주석을 사용하여 문제를 해결했습니다.

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

    @Autowired
    @Lazy
    private IGalaxyCommand iGalaxyCommand;



2

Max가 제안한대로 AbstractManager를 autowire하는 것이 올바른 방법이지만 이것도 잘 작동합니다.

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

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

2

최근에이 문제를 해결했는데 결과적으로 서비스 클래스에서 잘못된 주석을 가져 왔습니다. Netbeans에는 import 문을 숨기는 옵션이 있으므로 한동안 보지 못했습니다.

내가 사용했습니다 @org.jvnet.hk2.annotations.Service대신 @org.springframework.stereotype.Service.



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

동일한 문제가 도착하여 주석을 그대로 유지하고 디스패처 서블릿에서 :: 기본 패키지 스캔을 유지하여 com.*.해결했습니다.


1

이것은 당신을 도울 수 있습니다 :

내 프로젝트에도 같은 예외가 있습니다. 검색 후 @Autowired를 원하는 인터페이스를 구현하는 클래스에 @Service 주석이 없음을 발견했습니다.

코드에서 @Service 주석을 MailManager 클래스에 추가 할 수 있습니다.

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

@Service주석이 포함되어 있습니다 @Component. 둘 다 갖는 것은 중복됩니다.
AnthonyW

1

@Autowire MailManager mailManager 대신 아래와 같이 빈을 조롱 할 수 있습니다.

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

::
::

@MockBean MailManager mailManager;

또한 클래스 @MockBean MailManager mailManager;에서 별도로 구성 @SpringBootConfiguration하고 아래와 같이 초기화 할 수 있습니다.

@Autowire MailManager mailManager

1

내 패키지 특정 스캔을 다음과 같이 활성화 했음에도 불구하고 스프링 부트 응용 프로그램에서 동일한 문제에 직면했습니다.

@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

컨트롤러를 테스트하는 경우. 테스트 클래스에서 @WebAppConfiguration을 사용하는 것을 잊지 마십시오.


0

내 서비스 클래스에 자동 연결 종속성을 추가했지만 서비스 단위 테스트에서 삽입 된 모의에 추가하는 것을 잊었 기 때문에 이런 일이 발생했습니다.

단위 테스트 예외는 문제가 실제로 단위 테스트에있을 때 서비스 클래스의 문제를보고하는 것처럼 보였습니다. 돌이켜 보면 오류 메시지는 문제가 무엇인지 정확히 알려주었습니다.


0

나를 위해 일한 솔루션은 모든 관련 클래스를 @ContextConfiguration 테스트 클래스 주석에 .

테스트 할 클래스 MyClass.java에는 두 개의 자동 연결 구성 요소가 있습니다. AutowireAAutowireB. 여기 내 수정 사항입니다.

@ContextConfiguration(classes = {MyClass.class, AutowireA.class, AutowireB.class})
public class MyClassTest {
...
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.