#spring #maven #autowired
#spring #maven #автоматическое подключение
Вопрос:
Я пробую небольшое приложение и все еще новичок в Spring mvc framework. У меня есть класс контроллера и XML-файл конфигурации компонента. Я могу использовать компонент, если вызываю метод getBean(). Однако мой план состоит в том, чтобы использовать автоматическое подключение для ввода компонента в мой контроллер, а не использовать getBean(). Но я получаю ошибку. Я использую maven для создания своего проекта. Вот мой класс контроллера в пакете под src / main / java
package com.eat.menu.controller;
import java.util.Date;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.eat.admin.config.Globals.DishCategory;
import com.eat.admin.config.Globals.MenuStatus;
import com.eat.menu.model.Dish;
import com.eat.menu.model.Menu;
@Controller
public class MenuController {
private static int counter = 0;
private static final String VIEW_INDEX = "index";
private final static org.slf4j.Logger logger =
LoggerFactory.getLogger(MenuController.class);
@Autowired
private MongoTemplate mongoTemplate;
public MongoTemplate getMongoTemplate() {
return mongoTemplate;
}
public void setMongoTemplate(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
@RequestMapping(value = "/", method = RequestMethod.GET)
public String welcome(ModelMap model) {
model.addAttribute("message", "Welcome");
model.addAttribute("counter", counter);
logger.debug("[welcome] counter : {}", counter);
// Spring uses InternalResourceViewResolver and return back index.jsp
return VIEW_INDEX;
}
@RequestMapping(value = "/{name}", method = RequestMethod.GET)
public String welcomeName(@PathVariable String name, ModelMap model) {
model.addAttribute("message", "Welcome " name);
model.addAttribute("counter", counter);
logger.debug("[welcomeName] counter : {}", counter);
return VIEW_INDEX;
}
@RequestMapping(value = "/menu", method = RequestMethod.GET)
public String createMenu(ModelMap model) {
ApplicationContext ctx = new GenericXmlApplicationContext("BaseConfig.xml");
//Avoid using this
MongoOperations mongoOperation = (MongoOperations) ctx.getBean("mongoTemplate");
Dish dish1 = new Dish();
Date now = new Date();
dish1.setName("Butter Chicken");
dish1.setCategory(DishCategory.ENTREE);
dish1.setCreateDate(now);
dish1.setUpdateDate(now);
Dish dish2 = new Dish();
dish2.setName("Korma Chicken");
dish2.setCategory(DishCategory.ENTREE);
dish2.setCreateDate(now);
dish2.setUpdateDate(now);
Dish [] dishes = new Dish[2];
dishes[0] = dish1;
dishes[1] = dish2;
Menu menu = new Menu();
menu.setCompanyId(1);
menu.setCreateDate(now);
menu.setUpdateDate(now);
menu.setDishes(dishes);
menu.setMenuStatus(MenuStatus.ACTIVE);
mongoOperation.save(menu);
Query searchMenuQuery = new Query(Criteria.where("companyId").is(1));
// find the saved user again.
Menu m = mongoOperation.findOne(searchMenuQuery, Menu.class);
return VIEW_INDEX;
}
}
Вот мой baseConfig.xml в разделе src/main/ресурсы
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<context:annotation-config/>
<mongo:mongo host="127.0.0.1" port="27017" />
<mongo:db-factory dbname="eatMongoDB" />
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>
<bean id="menuController" class="com.eat.menu.controller.MenuController">
<property name="mongoTemplate" value="mongoTemplate"/>
</bean>
Пожалуйста, дайте мне знать, если я делаю что-то не так, потому что я получаю следующую ошибку:
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'menuController': Unsatisfied dependency expressed through field 'mongoTemplate': No qualifying bean of type [org.springframework.data.mongodb.core.MongoTemplate] found for dependency [org.springframework.data.mongodb.core.MongoTemplate]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.data.mongodb.core.MongoTemplate] found for dependency [org.springframework.data.mongodb.core.MongoTemplate]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:569)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:349)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:776)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:444)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:326)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4715)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5177)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:152)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1403)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.data.mongodb.core.MongoTemplate] found for dependency [org.springframework.data.mongodb.core.MongoTemplate]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1406)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1057)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1019)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:566)
... 24 more
I am adding 3 config files for clarity and let me know if anything may be required: The first one is pom file:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=»http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd«>
4.0.0
com.eat
EatApp
war
1.0-SNAPSHOT
EatApp Maven Webapp
http://maven.apache.org
<properties>
<jdk.version>1.8</jdk.version>
<spring.version>4.3.2.RELEASE</spring.version>
<jstl.version>1.2</jstl.version>
<junit.version>4.12</junit.version>
<logback.version>1.1.7</logback.version>
<jcl-over-slf4j.version>1.7.21</jcl-over-slf4j.version>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${jcl-over-slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<!-- Spring Framework -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Mongo dependencies -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.9.2.RELEASE</version>
</dependency>
<!-- jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.4</version>
</dependency>
</dependencies>
<build>
<finalName>EatApp</finalName>
<plugins>
<!-- Eclipse project -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.10</version>
<configuration>
<!-- Always download and attach dependencies source code -->
<downloadSources>true</downloadSources>
<downloadJavadocs>false</downloadJavadocs>
<!-- Avoid type mvn eclipse:eclipse -Dwtpversion=2.0 -->
<wtpversion>2.0</wtpversion>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
<!--
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/EatApp</path>
</configuration>
</plugin>
-->
</plugins>
</build>
web.xml:
<!-- <!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
-->
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>EatApp Web Application</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<!--
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/BaseConfig.xml
</param-value>
</init-param>
-->
<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>
И файл сервлета: mvc-dispatch-servlet:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.eat.menu.controller" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
Комментарии:
1. Зачем вам использовать @Autowired и установку установки?
2. Даже если я его не использую, он все равно выдает мне указанную выше ошибку
3. Удалите средство получения / установки для
MongoTemplate
, удалите<property>
из<bean id="menuController">
. Если он по-прежнему не работает, это то, что вы не включили, или это не тот код, который вы на самом деле используете (например, несоответствие «BaseConfig» и «BaseConfig»). У вас есть какие-либо другие файлы конфигурации XML? Вы уверены, что ваше приложение MVC также использует BaseConfig.xml ?4. Я сделал то же самое. Я добавил файл pom, web.xml и файл сервлета. Пожалуйста, дайте мне знать, если в конфигурации чего-то не хватает. Спасибо
Ответ №1:
Кажется, вы установили только файл конфигурации /WEB-INF/mvc-dispatcher-servlet.xml в параметре contextConfigLocation. Добавьте содержимое вашего baseConfig.xml к этому и попробуйте еще раз. Если это решит проблему, то позже вы сможете использовать несколько конфигурационных файлов.
Ответ №2:
Если вы хотите использовать аннотацию, сканирование компонентов должно быть определено в вашей конфигурации, вы можете указать spring, какому пакету требуется это автоматическое сканирование.
<context:component-scan base-package="com.xxx.xxx"/>
Исключение гласит: исключен как минимум 1 компонент, который квалифицируется как… это означает, что spring не может его найти.
Если вы хотите внедрить компонент в свой контроллер, @Resource
это намного лучше, чем @Autowired
. Потому что
@Autowired
вводит по типу. если вы хотите вводить по имени, вы должны добавить @Qualifier()
аннотацию. И если вы используете @Autowired
, вы должны убедиться, что компонент зависимостей существует. Если разрешено значение null, добавьте @Autowired(required=false)
. Я обнаружил, что в вашем исключении говорится
No qualifying bean of type [org.springframework.data.mongodb.core.MongoTemplate] found for dependency [org.springframework.data.mongodb.core.MongoTemplate]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1406)
Проверьте свой компонент MongoTemplate, возможно, он даже не существует или, возможно, ваш контейнер spring не может его найти.
@Autowired()
@Qualifier("mongoTemplate")
private MongoTemplate mongoTemplate; // Autowired. Inject by type. if you want to inject by name, you must add @Qualifier() annotation.
@Resource
Ввод по имени. если вы хотите ввести по имени
@Resource(name="mongoTemplate")
private MongoTemplate mongoTemplate; // Resource. Inject by name.
И самое главное, что @Resource
принадлежит J2EE
, @Autowired
принадлежит Spring
. Оба они решат проблему, но
если вы выясните, как это сделать, вам станет лучше. Хотелось бы, чтобы это помогло вам.
Комментарии:
1. Автоматическое подключение по имени в значительной степени противоречит цели использования IoC и делает рефакторинг чрезвычайно сложным из-за того, насколько хрупким становится приложение. Этот совет также не решит проблему, так что это скорее комментарий, чем ответ.
2. Нет, похоже, ничего из этого не работает. Он не распознает компонент MongoTemplate. Кажется, это может быть связано с конфигурацией, но я не уверен, как, потому что я определил свои компоненты в baseConfig.xml и я поместил этот файл в java/main/resources. Я понимаю, что все, что находится в разделе ресурсы, считывается Springmvc. Если это не так, пожалуйста, дайте мне знать, как я могу включить мой baseConfig.xml файл такой, чтобы были доступны объявленные в нем компоненты.
3. идентификатор компонента @
mongoTemplate
sirajnadwar определен в вашей конфигурации. Я думаю@Autowired@Qualifier("mongoTemplate")private MongoTemplate mongoTemplate;
, этого достаточно. Или@Resource(name="mongoTemplate")private MongoTemplate mongoTemplate;