@Autowired - Tidak ada jenis kacang yang memenuhi syarat yang ditemukan untuk ketergantungan


90

Saya telah memulai proyek saya dengan membuat entitas, layanan, dan pengujian JUnit untuk layanan menggunakan Spring dan Hibernate. Semua ini bekerja dengan baik. Kemudian saya telah menambahkan spring-mvc untuk membuat aplikasi web ini menggunakan banyak tutorial langkah demi langkah yang berbeda, tetapi ketika saya mencoba membuat Pengontrol dengan anotasi @Autowired, saya mendapatkan kesalahan dari Glassfish selama penerapan. Saya rasa untuk beberapa alasan Spring tidak melihat layanan saya, tetapi setelah banyak upaya saya masih tidak bisa mengatasinya.

Tes untuk layanan dengan

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

dan

@Autowired
MailManager mailManager;

bekerja dengan baik.

Pengontrol tanpa @Autowired juga, saya dapat membuka proyek saya di browser web tanpa masalah.

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

}

Kesalahan:

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

Maaf untuk banyak kode, tapi saya tidak tahu apa yang bisa menyebabkan kesalahan itu lagi.

Ditambahkan

Saya telah membuat antarmuka:

@Component
public interface IMailManager {

alat tambahan:

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

dan mengubah autowired:

@Autowired
public IMailManager mailManager;

Tapi masih ada kesalahan (juga ketika saya mencoba dengan @Qualifier)

..Tidak bisa autowire field: public pl.com.radzikowski.webmail.service.IMailManager pl.com.radzikowski.webmail.controller.HomeController.mailManager ...

Saya sudah mencoba dengan kombinasi yang berbeda dari @Component dan @Transactional juga.

Bukankah saya harus menyertakan beans.xml di web.xml entah bagaimana?


Bagaimana Anda memuat beans.xml?
Michael Wiles

sekarang bagaimana meninggalkan hanya satu dari MailManagerInterfacedan IMailManager? :)
Patison

Maaf, saya salah menempel kode. Dalam program saya ada IMailManagerdimana - mana.
Radzikowski

ah, tepatnya .. tambahkan <import resource="classpath:/beans.xml"/>kemvc-dispatcher-servlet.xml
Patison

Ngomong-ngomong, apakah Anda sudah mencoba keputusan @emd?
Patison

Jawaban:


81

Anda harus memasang antarmuka otomatis, AbstractManagerbukan kelas MailManager. Jika Anda memiliki implementasi yang berbeda AbstractManagerAnda dapat menulis @Component("mailService")dan kemudian @Autowired @Qualifier("mailService")menggabungkan ke autowire kelas tertentu.

Hal ini disebabkan oleh fakta bahwa Spring membuat dan menggunakan objek proxy berdasarkan antarmuka.


2
Terima kasih tetapi masih tidak berhasil (kesalahan yang sama). Saya menambahkan perubahan di postingan. Mungkin saya tidak menyertakan / mencari sesuatu dalam proyek saya dengan benar?
Radzikowski

Saya bertanya-tanya apakah ada cara untuk melakukan sesuatu seperti @Autowired AbstractManager[] abstractManagersitu yang berisi semua implementasinya.
WoLfPwNeR

@WoLfPwNeR Ini harus bekerja persis seperti yang Anda tulis. Lihat tautan
Patison

Mengapa tidak MailManager?
Alex78191

Saya memiliki dua @Servicekelas yang menerapkan antarmuka yang sama. Keduanya berada @Autowireddi kelas lain. Awalnya itu menyebabkan masalah yang sama seperti postingan asli ketika saya menggunakan tipe kelas tertentu. Mengikuti jawaban ini, saya mengubah menggunakan jenis Antarmuka dengan @Qualifier("myServiceA")dan @Qualifier("myServiceB"), dan masalah teratasi. Terima kasih!
xialin

27

Saya mengalami ini karena pengujian saya tidak dalam paket yang sama dengan komponen saya. (Saya telah mengganti nama paket komponen saya, tetapi bukan paket pengujian saya.) Dan saya menggunakan @ComponentScandi @Configurationkelas pengujian saya , jadi pengujian saya tidak menemukan komponen yang mereka andalkan.

Jadi, periksa kembali jika Anda mendapatkan kesalahan ini.


2
Ini berhasil untuk saya. Pengujian saya gagal ketika saya memfaktorkan ulang kode untuk pindah ke nama paket baru karena saya menggunakan nama paket lama di @ComponentScan.
Vijay Vepakomma

1
Bagaimana cara menggunakan @Configurationkelas dari src/maindalam src/test?
Alex78191

10

Masalahnya adalah bahwa konteks aplikasi dan konteks aplikasi web terdaftar di WebApplicationContext selama startup server. Saat Anda menjalankan pengujian, Anda harus secara eksplisit memberi tahu konteks mana yang akan dimuat.

Coba ini:

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

1
Bagaimana cara melakukannya jika saya menggunakan Spring Boot?
Alex78191

Saya lupa tentang mengonfigurasi pemindaian komponen untuk dependensi maven dan berjuang dengan ini seperti setahun sekali.
b15

Jika Anda berbicara tentang aplikasi itu sendiri dan bukan tes integrasi, untuk Spring boot Anda dapat melakukannya seperti ini: @SpringBootApplication(scanBasePackages = { "com.package.one", "com.package.two" })
b15

5

Menghabiskan banyak waktu saya dengan ini! Salahku! Kemudian menemukan bahwa kelas tempat saya mendeklarasikan anotasi Serviceatau Componentbertipe abstrak. Telah mengaktifkan log debug di Springframework tetapi tidak ada petunjuk yang diterima. Silakan periksa apakah kelasnya berjenis abstrak. Jika kemudian, aturan dasar yang diterapkan, tidak dapat membuat instance kelas abstrak.


1
Anda menyelamatkan hari saya Pak, ini sangat sulit untuk dideteksi!
Japheth Ongeri - inkalimeva

4

Saya menghadapi masalah yang sama saat memasang kabel otomatis kelas dari salah satu file jar saya. Saya memperbaiki masalah ini dengan menggunakan anotasi @Lazy:

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

    @Autowired
    @Lazy
    private IGalaxyCommand iGalaxyCommand;



2

Cara yang benar adalah dengan autowire AbstractManager, seperti yang disarankan Max, tetapi ini akan bekerja dengan baik juga.

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

dan

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

2

Saya berlari ke ini baru-baru ini, dan ternyata, saya telah mengimpor anotasi yang salah di kelas layanan saya. Netbeans memiliki opsi untuk menyembunyikan pernyataan impor, itulah mengapa saya tidak melihatnya selama beberapa waktu.

Saya telah menggunakan, @org.jvnet.hk2.annotations.Servicebukan @org.springframework.stereotype.Service.



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

masalah yang sama tiba, saya menyelesaikannya dengan menjaga anotasi tetap utuh dan di dispatcher servlet :: menjaga pemindaian paket dasar karena com.*.ini berfungsi untuk saya.


1

Ini dapat membantu Anda:

Saya memiliki pengecualian yang sama dalam proyek saya. Setelah mencari sementara saya menemukan bahwa saya kehilangan anotasi @Service ke kelas tempat saya mengimplementasikan antarmuka yang saya ingin @Autowired.

Dalam kode Anda, Anda dapat menambahkan anotasi @Service ke kelas MailManager.

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

The @Servicepenjelasan mengandung @Component. Memiliki keduanya itu mubazir.
AnthonyW

1

Daripada @Autowire MailManager mailManager, Anda dapat membuat tiruan kacang seperti yang diberikan di bawah ini:

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

::
::

@MockBean MailManager mailManager;

Selain itu, Anda dapat mengonfigurasi @MockBean MailManager mailManager;secara terpisah di @SpringBootConfigurationkelas dan menginisialisasi seperti di bawah ini:

@Autowire MailManager mailManager

1

Menghadapi masalah yang sama di aplikasi boot musim semi saya meskipun saya mengaktifkan pemindaian khusus paket saya seperti

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

Namun, masalah tersebut diselesaikan dengan menyediakan @ComponentScan({"com.*"})di kelas Aplikasi saya.


0

Dugaan saya adalah di sini

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

semua anotasi pertama-tama dinonaktifkan oleh use-default-filters = "false" dan kemudian hanya anotasi @Controller yang diaktifkan. Karenanya, anotasi @Component Anda tidak diaktifkan.


0

Jika Anda menguji pengontrol Anda. Jangan lupa untuk menggunakan @WebAppConfiguration di kelas pengujian Anda.


0

Saya mengalami ini terjadi karena saya menambahkan ketergantungan autowired ke kelas layanan saya tetapi lupa menambahkannya ke tiruan yang disuntikkan dalam pengujian unit layanan saya.

Pengecualian pengujian unit tampaknya melaporkan masalah di kelas layanan ketika masalah sebenarnya ada di pengujian unit. Dalam retrospeksi, pesan kesalahan memberitahu saya apa masalahnya.


0

Solusi yang berhasil bagi saya adalah menambahkan semua kelas yang relevan ke @ContextConfiguration anotasi untuk kelas pengujian.

Kelas yang akan diuji MyClass.java, memiliki dua komponen yang dipasang secara otomatis: AutowireAdan AutowireB. Ini perbaikan saya.

@ContextConfiguration(classes = {MyClass.class, AutowireA.class, AutowireB.class})
public class MyClassTest {
...
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.