前言
所謂Spring應用上下文混合配置,指的是配置一部分在xml文件,一部分在java代碼。這種方式不是很常見,常見的要麼是純xml文件配置,要麼是純java編程配置。純java編程配置後續章節我們會詳細講解。關於這兩種純配置方式的比較,我們前面的章節已經提過。
根應用上下文配置
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:annotation-config />
<context:component-scan base-package="com.gxz" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Service" />
</context:component-scan>
</beans>
DispatcherServlet應用上下文配置
<?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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<mvc:annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.gxz" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
</beans>
業務邏輯相關的bean
package com.gxz;
import org.springframework.stereotype.Service;
@Service
public class StudentImp implements Student {
@Override
public String sayHi(String name) {
return "Hi," + name;
}
public StudentImp() {
super();
System.out.println("StudentImp()");
}
}
package com.gxz;
public interface Student {
String sayHi(String name);
}
控制器bean
package com.gxz;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class StudentController {
@Autowired
private Student student;
@ResponseBody
@RequestMapping("/")
public String sayHi() {
return "Hi!";
}
@ResponseBody
@RequestMapping(value="/say", params="name")
public String say(@RequestParam("name") String name) {
return student.sayHi(name);
}
public void setStudent(Student student) {
this.student = student;
}
public StudentController() {
super();
System.out.println("StudentController()");
}
}
package com.gxz;
import org.springframework.stereotype.Service;
@Service
public class ComputerStudent implements Student {
public String sayHi(String name) {
return "Hi, " + name + ".Happy to see again.";
}
}
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'studentController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.gxz.Student com.gxz.StudentController.student; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.gxz.Student] is defined: expected single matching bean but found 2: computerStudent,studentImp
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.gxz.Student com.gxz.StudentController.student; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.gxz.Student] is defined: expected single matching bean but found 2: computerStudent,studentImp
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.gxz.Student] is defined: expected single matching bean but found 2: computerStudent,studentImp
若要解決這個異常,就必須告訴Spring,Spring在實例化bean StudentController時,爲之注入依賴Student時明確指定是哪一個bean(computerStudent,studentImp二選一)。@Autowired
@Qualifier("computerStudent")
private Student student;
org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from ServletContext resource [/WEB-INF/rootContext.xml]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'studentImp' for bean class [com.gxz.StudentImp] conflicts with existing, non-compatible bean definition of same name and class [com.gxz.config.StudentImp]
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'studentImp' for bean class [com.gxz.StudentImp] conflicts with existing, non-compatible bean definition of same name and class [com.gxz.config.StudentImp]
package com.gxz.config;
import org.springframework.stereotype.Service;
import com.gxz.Student;
@Service("configStudentImp")
public class StudentImp implements Student {
public String sayHi(String name) {
return "Hi, " + name + ".Happy to see again.";
}
}
註解@Autowired配置的位置
private Student student;
@Autowired
public void setStudent(Student student) {
this.student = student;
}
private Student student;
@Autowired
public StudentController(Student student) {
super();
this.student = student;
System.out.println("StudentController() with argument.");
}
@Autowired
public StudentController(Student student) {
super();
this.student = student;
System.out.println("StudentController() with argument student.");
}
@Autowired
public StudentController( Teacher teacher) {
super();
this.teacher = teacher;
System.out.println("StudentController() with arguments teacher.");
}
org.springframework.beans.factory.BeanCreationException: Invalid autowire-marked constructor: public com.gxz.StudentController(com.gxz.Student). Found another constructor with 'required' Autowired annotation: public com.gxz.StudentController(com.gxz.Student,com.gxz.Teacher)
關於排除過濾器存在的問題
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:annotation-config />
<context:component-scan base-package="com.gxz" use-default-filters="false">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
</beans>