问题
I have user service that treat user entity, and @Autowired in user controller class before use user service. so, I got the error:
Unsatisfied 'required' dependency of type [class com.yes.service.UserService]. Expected at least 1 matching bean
here the codes:
userService
package com.yes.service;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yes.domain.User;
import com.yes.repository.RoleRepository;
import com.yes.repository.UserRepository;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
public User create(User user) {
user.setId(UUID.randomUUID().toString());
user.getRole().setId(UUID.randomUUID().toString());
// We must save both separately since there is no cascading feature
// in Spring Data MongoDB (for now)
roleRepository.save(user.getRole());
return userRepository.save(user);
}
public User read(User user) {
return user;
}
public List<User> readAll() {
return userRepository.findAll();
}
public User update(User user) {
User existingUser = userRepository.findByUsername(user.getUserName());
if (existingUser == null) {
return null;
}
existingUser.setFirstName(user.getFirstName());
existingUser.setLastName(user.getLastName());
existingUser.getRole().setRole(user.getRole().getRole());
// We must save both separately since there is no cascading feature
// in Spring Data MongoDB (for now)
roleRepository.save(existingUser.getRole());
return userRepository.save(existingUser);
}
public Boolean delete(User user) {
User existingUser = userRepository.findByUsername(user.getUserName());
if (existingUser == null) {
return false;
}
// We must delete both separately since there is no cascading feature
// in Spring Data MongoDB (for now)
roleRepository.delete(existingUser.getRole());
userRepository.delete(existingUser);
return true;
}
}
userController (where i use the userService, and the problem is)
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService service;
@RequestMapping
public String getUsersPage() {
return "users";
}
@RequestMapping(value="/records")
public @ResponseBody UserListDto getUsers() {
UserListDto userListDto = new UserListDto();
userListDto.setUsers(service.readAll());
return userListDto;
}
@RequestMapping(value="/get")
public @ResponseBody User get(@RequestBody User user) {
return service.read(user);
}
@RequestMapping(value="/create", method=RequestMethod.POST)
public @ResponseBody User create(
@RequestParam String username,
@RequestParam String password,
@RequestParam String firstName,
@RequestParam String lastName,
@RequestParam Integer role) {
Role newRole = new Role();
newRole.setRole(role);
User newUser = new User();
newUser.setUserName(username);
newUser.setPassword(password);
newUser.setFirstName(firstName);
newUser.setLastName(lastName);
newUser.setRole(newRole);
return service.create(newUser);
}
@RequestMapping(value="/update", method=RequestMethod.POST)
public @ResponseBody User update(
@RequestParam String username,
@RequestParam String firstName,
@RequestParam String lastName,
@RequestParam Integer role) {
Role existingRole = new Role();
existingRole.setRole(role);
User existingUser = new User();
existingUser.setUserName(username);
existingUser.setFirstName(firstName);
existingUser.setLastName(lastName);
existingUser.setRole(existingRole);
return service.update(existingUser);
}
@RequestMapping(value="/delete", method=RequestMethod.POST)
public @ResponseBody Boolean delete(
@RequestParam String username) {
User existingUser = new User();
existingUser.setUserName(username);
return service.delete(existingUser);
}
}
spring-data.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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
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.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.1.xsd">
<context:property-placeholder
properties-ref="deployProperties" />
<!-- MongoDB host -->
<mongo:mongo host="${mongo.host.name}" port="${mongo.host.port}" />
<!-- Template for performing MongoDB operations -->
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"
c:mongo-ref="mongo" c:databaseName="${mongo.db.name}" />
<!-- Activate Spring Data MongoDB repository support -->
<mongo:repositories base-package="com.yes.repository" mongo-template-ref="mongoTemplate"/>
<!-- Service for initializing MongoDB with sample data using MongoTemplate -->
<bean id="initMongoService" class="com.yes.service.InitMongoService" init-method="init"/>
</beans>
servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
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">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<context:component-scan base-package="com.yes.controller"/>
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
applicationContext.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:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<context:property-placeholder
properties-ref="deployProperties" />
<!-- Activates various annotations to be detected in bean classes -->
<context:annotation-config />
<!-- Scans the classpath for annotated components that will be auto-registered
as Spring beans. For example @Controller and @Service. Make sure to set the
correct base-package -->
<context:component-scan base-package="com.yes.domain"/>
<context:component-scan base-package="com.yes.dto"/>
<context:component-scan base-package="com.yes.service"/>
<!-- Configures the annotation-driven Spring MVC Controller programming
model. Note that, with Spring 3.0, this tag works in Servlet MVC only! -->
<mvc:annotation-driven />
<mvc:resources mapping="/resources/**" location="/resources/" />
<!-- Imports datasource configuration -->
<import resource="spring-data.xml" />
<bean id="deployProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean"
p:location="/WEB-INF/spring/spring.properties" />
the error stack:
ERROR: org.springframework.web.servlet.DispatcherServlet - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.yes.service.UserService com.yes.controller.UserController.service; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.yes.service.UserService] 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)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/applicationContext.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
EDIT: the question is after fix the errors written in Sotirios Delimanolis answer and comment.
What is the problem cause the error?
Answer: The problem was what was described in Sotirios Delimanolis answer. The Exact solution described in comments on his answer
thank you
回答1:
Your application context and servlet context are component scanning over the same packages.
Your application context
<context:component-scan base-package="com.yes" />
Versus everything in servlet context
<context:component-scan base-package="com.yes.service"/>
<context:component-scan base-package="com.yes.controller"/>
<context:component-scan base-package="com.yes.domain"/>
<context:component-scan base-package="com.yes.repository"/>
<context:component-scan base-package="com.yes.dto"/>
So some beans will be overriden. You don't want this. Your servlet context should scan for @Controller
beans. Your application context should scan for everything else, but don't make your application context scan for things already scanned by your child (imported) data context. Fix your package declarations so all of these are disjoint.
来源:https://stackoverflow.com/questions/18473236/spring-mvc-autowired-error-unsatisfied-required-dependency-of-type