此前有一个疑问:
@Resource
private TestDAO testDAO;
这样的一句话,Spring怎么找到TestDAOImpl,使其成为
private TestDAO testDAO = new TestDAOImpl();
1.先从Bean注入说起,谈谈注入的装配类型
Spring auto-wire的 五种方式:
1:no 默认的方式是不进行自动装配,通过手工设置ref 属性来进行装配bean
2:byName 通过参数名 自动装配,如果一个bean的name 和另外一个bean的 property 相同,就自动装配。
3:byType 通过参数的数据类型自动自动装配,如果一个bean的数据类型和另外一个bean的property属性的数据类型兼容,就自动装配
4:construct 构造方法中的参数通过byType的形式,自动装配。
5:auto detect 如果有默认的构造方法,通过 construct的方式自动装配,否则使用 byType的方式自动装配。用于spring2.5 ,spring3.0测试不通过,估计是废弃了。
首先定义测试需要的类:
package com.myapp.core.autowire;
public class Book {
public String toString(){
return "I'm a book, read me......";
}
}
package com.myapp.core.autowire;
public class Person {
private Book book;
public Person(Book book){
this.book= book;
}
public void setBook(Book book){
this.book = book;
}
public String toString(){
return "I'm a person I want to read a book "+ book;
}
public Person(){
}
}
<?xml version="1.0" encoding="UTF-8"?>
http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="Index of /schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- more bean definitions for data access objects go here -->
<bean id="person" class="com.myapp.core.autowire.Person">
<property name="book" ref="book" />
</bean>
<bean id="book" class="com.myapp.core.autowire.Book"></bean>
</beans>
编写测试类:
package com.myapp.core.autowire;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("resource/autowire.xml");
Person person = (Person)context.getBean("person");
System.out.println(person.toString());
}
}
测试结果:
I'm a person I want to read a book I'm a book, read me......
二:通过byName 自动装配:
修改配置文件如下:
在这个例子中通过bean的属性名自动装配;因为这个
person bean的属性 book和配置文件中id为book的名字相同,所以Spring将通过setBook(Book book)自动装配。
<!-- byName -->
<bean id="person" class="com.myapp.core.autowire.Person" autowire="byName">
</bean>
<bean id="book" class="com.myapp.core.autowire.Book"></bean>
运行测试类:依然得到如上测试结果。
三:通过byType自动装配:
在这个例子中通过bean的属性名的类型进行自动装配;因为 person bean属性 book的类型和配置文件中id为book的类型相同,。所以spring通过setBook(Book book)自动装配。
修改配置文件如下;
<!-- byType -->
<bean id="person" class="com.myapp.core.autowire.Person" autowire="byType"/>
<bean id="book" class="com.myapp.core.autowire.Book"></bean>
四:通过construct自动装配:
通过构造方法的参数的数据类型进行自动装配,在这个例子中因为person的构造方法参数是Book类型,和配置文件中的id为book的类型相同,所以spring通过Person(Book book)构造方法进行自动装配。
修改配置文件如下:
[html]
<!-- construct -->
<bean id="person" class="com.myapp.core.autowire.Person" autowire="constructor"/>
<bean id="book" class="com.myapp.core.autowire.Book"></bean>
Spring 3.0配置的xml不能用于autodetect,spring3.0应该是去掉了这个功能,改用spring2.5配置可以顺利通过测试,
首先使用construct的自动装配形式进行装配,如果没有construct就通过 byType的形式进行自动装配。<beans
http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="Index of /schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="person" class="com.myapp.core.autowire.Person" autowire="autodetect" />
<bean id="book" class="com.myapp.core.autowire.Book"></bean>
</beans>
测试结果:
I'm a person I want to read a book I'm a book, read me......
public interface UserDao{
....
}
@Repository("userDao")
public class UserDaoImpl implements UserDao{
...
}
public class UserServiceImpl{
private UserDao userDao;
@Resource("userDao") //通过@Repository("userDao")注解找到UserServiceImpl类的
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
....
....
}
Resource("userDao")
private UserDao userDao;
此处是通过byName自动装配的
private UserDao userDao;
@Resource
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Resource
private UserDao userDao;
此处通过ByType自动装配
@Resource
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
xml文件里,没有一个名字为userDao的bean
<bean id="userDaoImpl" class="com.fz.annotation.dao.impl.UserDaoImpl">
</bean>
<bean id="userDaoImpl1" class="com.fz.annotation.dao.impl.UserDaoImpl">
</bean>
<bean id="userService" class="com.fz.annotation.service.UserService">
</bean>
此时测试的时候会报错,因为默认按byName,此时是没有名字为userDao的bean的,所以再次按byType,但是byType会出现两个相同类型的bean
所以会报错。
此时,删掉一个bean的定义
<bean id="userDaoImpl1" class="com.fz.annotation.dao.impl.UserDaoImpl">
</bean>
<bean id="userService" class="com.fz.annotation.service.UserService">
</bean>
再次测试的时候就正常,不会报错。
原因:
实例源自:
https://www.zhihu.com/question/39361250
http://www.cnblogs.com/meet/p/4758211.html