Я начал свой проект с создания сущностей, сервисов и тестов JUnit для сервисов, использующих Spring и Hibernate. Все это прекрасно работает. Затем я добавил spring -mvc, чтобы сделать это веб-приложение с использованием множества различных пошаговых руководств, но когда я пытаюсь создать контроллер с аннотацией @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 <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)
.. Не удалось выполнить автоматическое подключение поля: public pl.com.radzikowski.webmail.service.IMailManager pl.com.radzikowski.webmail.controller.HomeController.mailManager ...
Я тоже пробовал разные комбинации @Component и @Transactional.
Разве я не должен как-то включить beans.xml в web.xml?
источник
MailManagerInterface
иIMailManager
? :)IMailManager
везде.<import resource="classpath:/beans.xml"/>
кmvc-dispatcher-servlet.xml
Ответы:
Вы должны autowire интерфейс
AbstractManager
вместо классаMailManager
. Если у вас есть разные реализации,AbstractManager
вы можете написать,@Component("mailService")
а затем@Autowired @Qualifier("mailService")
комбинировать его для определенного класса autowire.Это связано с тем, что Spring создает и использует прокси-объекты на основе интерфейсов.
источник
@Autowired AbstractManager[] abstractManagers
, содержащее все его реализации.MailManager
?@Service
класса, реализующие один и тот же интерфейс. Оба находятся@Autowired
в другом классе. Изначально это вызывало ту же проблему, что и исходное сообщение, когда я использовал определенный тип класса. После этого ответа я перешел на использование типа интерфейса с разными@Qualifier("myServiceA")
и@Qualifier("myServiceB")
, и проблема была решена. Благодарность!У меня это произошло, потому что мои тесты не были в том же пакете, что и мои компоненты. (Я переименовал свой пакет компонентов, но не свой тестовый пакет.) И я использовал его
@ComponentScan
в своем тестовом@Configuration
классе, поэтому мои тесты не находили компоненты, на которые они полагались.Итак, дважды проверьте это, если вы получите эту ошибку.
источник
@Configuration
класс изsrc/main
вsrc/test
?Дело в том, что и контекст приложения, и контекст веб-приложения регистрируются в WebApplicationContext во время запуска сервера. При запуске теста вы должны явно указать, какие контексты загружать.
Попробуй это:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:/beans.xml", "/mvc-dispatcher-servlet.xml"})
источник
@SpringBootApplication(scanBasePackages = { "com.package.one", "com.package.two" })
Я потратил на это много времени! Виноват! Позже обнаружили , что класс , на котором я объявил аннотацию
Service
илиComponent
был типа реферата. Включил журналы отладки на Springframework, но никаких подсказок получено не было. Пожалуйста, проверьте, имеет ли класс абстрактный тип. Если тогда применяется основное правило, не может создать экземпляр абстрактного класса.источник
Можете ли вы попробовать аннотировать только вашу конкретную реализацию
@Component
? Возможно, следующий ответ может помочь. Это вроде похожая проблема. Я обычно помещаю аннотации Spring в классы реализации.https://stackoverflow.com/a/10322456/2619091
источник
Я столкнулся с той же проблемой при автоматическом подключении класса из одного из моих файлов jar. Я исправил проблему, используя аннотацию @Lazy:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; @Autowired @Lazy private IGalaxyCommand iGalaxyCommand;
источник
Правильный способ - автоматическое подключение AbstractManager, как предлагал Макс, но это тоже должно работать нормально.
@Autowired @Qualifier(value="mailService") public MailManager mailManager;
а также
@Component("mailService") @Transactional public class MailManager extends AbstractManager { }
источник
Недавно я столкнулся с этим и, как оказалось, импортировал неправильную аннотацию в свой класс обслуживания. В Netbeans есть возможность скрывать операторы импорта, поэтому я не видел этого некоторое время.
Я использовал
@org.jvnet.hk2.annotations.Service
вместо@org.springframework.stereotype.Service
.источник
увидеть больше этот URL:
http://www.baeldung.com/spring-nosuchbeandefinitionexception
источник
<context:component-scan base-package="com.*" />
возникла та же проблема, я решил ее, сохранив аннотации нетронутыми и в диспетчере servlet :: сохраняя сканирование базового пакета, поскольку
com.*.
это сработало для меня.источник
Это может помочь вам:
У меня такое же исключение в моем проекте. После поиска, когда я обнаружил, что мне не хватает аннотации @Service для класса, в котором я реализую интерфейс, который я хочу использовать @Autowired.
В своем коде вы можете добавить аннотацию @Service к классу MailManager.
@Transactional @Service public class MailManager extends AbstractManager implements IMailManager {
источник
@Service
Аннотаций содержит@Component
. И то, и другое - излишне.Вместо @Autowire MailManager mailManager вы можете издеваться над bean-компонентом, как показано ниже:
import org.springframework.boot.test.mock.mockito.MockBean; :: :: @MockBean MailManager mailManager;
Кроме того, вы можете настроить
@MockBean MailManager mailManager;
отдельно в@SpringBootConfiguration
классе и инициализировать, как показано ниже:@Autowire MailManager mailManager
источник
Столкнулся с той же проблемой в моем приложении весенней загрузки, хотя у меня было включено сканирование моего пакета, например
@SpringBootApplication(scanBasePackages={"com.*"})
Но проблема была решена путем предоставления
@ComponentScan({"com.*"})
в моем классе Application.источник
Я предполагаю, что здесь
<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 не включена.
источник
Если вы тестируете свой контроллер. Не забудьте использовать @WebAppConfiguration в своем тестовом классе.
источник
У меня это произошло, потому что я добавил автоматическую зависимость к своему классу обслуживания, но забыл добавить ее к внедренным имитам в моем модульном тесте службы.
Исключение модульного теста, по-видимому, сообщало о проблеме в классе обслуживания, когда проблема действительно была в модульном тесте. Оглядываясь назад, я могу сказать, что в сообщении об ошибке было точно сказано, в чем проблема.
источник