spring IOC注入方式有三种:
1.构造器注入
2.setter注入
3.注解方式
构造器注入, service层调用dao层,向service注入dao
package com.skymr.spring.test.dao;
/*
* 对数据库表UserInfo的增删查找操作接口
*/
public interface UserInfoDao {
public void save();
public void update();
public void delete();
public void find();
}
package com.skymr.spring.test.dao.impl;
import com.skymr.spring.test.dao.UserInfoDao;
public class UserInfoDaoBean implements UserInfoDao{
public void delete() {
System.out.println("删除一个用户");
}
public void find() {
System.out.println("查找一个用户");
}
public void save() {
System.out.println("保存一个用户");
}
public void update() {
System.out.println("更新一个用户");
}
}
package com.skymr.spring.test.service;
public interface UserInfoService {
public void update();
public void save();
public void delete();
public void find();
}
package com.skymr.spring.test.service.impl;
import com.skymr.spring.test.dao.UserInfoDao;
import com.skymr.spring.test.service.UserInfoService;
public class UserInfoServiceBean implements UserInfoService{
private UserInfoDao userInfoDao;
private String name;
public UserInfoServiceBean(UserInfoDao userInfoDao, String name){
this.userInfoDao = userInfoDao;
this.name = name;
}
public void delete() {
userInfoDao.delete();
}
public void find() {
userInfoDao.find();
}
public void save() {
userInfoDao.save();
}
public void update() {
userInfoDao.update();
}
}
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id = "userInfoDao" class = "com.skymr.spring.test.dao.impl.UserInfoDaoBean"></bean>
<!-- 通过构造器方式注入 -->
<bean id = "userInfoService" class="com.skymr.spring.test.service.impl.UserInfoServiceBean">
<constructor-arg index="0" type="com.skymr.spring.test.dao.UserInfoDao" ref="userInfoDao"></constructor-arg>
<constructor-arg index="1" type="java.lang.String" value="skymr"></constructor-arg>
</bean>
</beans>
测试:
package com.skymr.spring.test;
import org.junit.BeforeClass;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
@BeforeClass
public static void setUpBeforeClass() throws Exception{
}
@org.junit.Test
public void instanceSpring(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
UserInfoService userInfoService = (UserInfoService) ctx.getBean("userInfoService");
userInfoService.save();
}
@org.junit.Test
public void springIOCTest(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
com.skymr.spring.test.service.UserInfoService userInfoService = (com.skymr.spring.test.service.UserInfoService) ctx.getBean("userInfoService");
userInfoService.save();
}
}
结果
保存一个用户
2.Setter方式注入和注解注入
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean id = "userInfoDao" class = "com.skymr.spring.test.dao.impl.UserInfoDaoBean"></bean>
<bean id = "userInfoService" class="com.skymr.spring.test.service.impl.UserInfoServiceBean">
<property name="name" value="skymr"></property>
</bean>
<context:component-scan base-package="springlive.learn.component"/>
<context:annotation-config></context:annotation-config>
</beans>
xmlns属性修改过了
<context:component-scan base-package="springlive.learn.component"/>
<context:annotation-config></context:annotation-config>
这两个配置可都以打开context的命名空间,到底使用哪一个啊?
package com.skymr.spring.test.service.impl;
import javax.annotation.Resource;
import com.skymr.spring.test.dao.UserInfoDao;
import com.skymr.spring.test.service.UserInfoService;
public class UserInfoServiceBean implements UserInfoService{
@Resource
private UserInfoDao userInfoDao;
private String name;
public UserInfoServiceBean(UserInfoDao userInfoDao, String name){
this.userInfoDao = userInfoDao;
this.name = name;
}
public void setName(String name){
this.name = name;
}
public UserInfoServiceBean(){
}
public void delete() {
userInfoDao.delete();
}
public void find() {
userInfoDao.find();
}
public void save() {
userInfoDao.save();
}
public void update() {
userInfoDao.update();
}
}
userInfoDao属性使用注解方式注入,name使用setter方式注入
当不使用构造器方式注入时,bean类必须要有无参构造器(不写构造器或声明空的构造器),不然会抛出异常
使用setter方式注入时,必须实现属性的setter方法
Autowired默认按类型装配
Resource默认按名称装配,找不到与名称相配的Bean时,才会按类型装配
例:
在xml配置中多配几个UserInfoDaoBean
<?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-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean id = "userInfoDao" class = "com.skymr.spring.test.dao.impl.UserInfoDaoBean"></bean>
<bean id = "userInfoDao1" class = "com.skymr.spring.test.dao.impl.UserInfoDaoBean"></bean>
<bean id = "userInfoService" class="com.skymr.spring.test.service.impl.UserInfoServiceBean">
<property name="name" value="skymr"></property>
</bean>
<context:component-scan base-package="springlive.learn.component"/>
<context:annotation-config></context:annotation-config>
</beans>
再修改UserInfoServiceBean.class, 换了个UserInfoDao的名称,换成qaa, 注解从@Resource改成了@Autowired
package com.skymr.spring.test.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import com.skymr.spring.test.dao.UserInfoDao;
import com.skymr.spring.test.service.UserInfoService;
public class UserInfoServiceBean implements UserInfoService{
@Autowired
private UserInfoDao qaa;
private String name;
public UserInfoServiceBean(UserInfoDao userInfoDao, String name){
this.qaa = userInfoDao;
this.name = name;
}
public void setName(String name){
this.name = name;
}
public UserInfoServiceBean(){
}
public void delete() {
qaa.delete();
}
public void find() {
qaa.find();
}
public void save() {
qaa.save();
}
public void update() {
qaa.update();
}
}
测试后抛出了异常
*****再将qaa改回userInfoDao,又正常了,为什么呢,它注入是个哪个bean呢?我觉得会是userInfoDao这个bean,因为名称和它一样,再测试下吧
例:
package com.skymr.spring.test.dao.impl;
import com.skymr.spring.test.dao.UserInfoDao;
public class UserInfoDaoBean implements UserInfoDao{
//用于判别bean
private String name;
public void setName(String name){
this.name = name;
}
public void delete() {
System.out.println(name + "删除一个用户");
}
public void find() {
System.out.println(name + "查找一个用户");
}
public void save() {
System.out.println(name + "保存一个用户");
}
public void update() {
System.out.println(name + "更新一个用户");
}
}
<?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-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean id = "userInfoDao" class = "com.skymr.spring.test.dao.impl.UserInfoDaoBean">
<property name="name" value = "userInfoDao"></property>
</bean>
<bean id = "userInfoDao1" class = "com.skymr.spring.test.dao.impl.UserInfoDaoBean">
<property name="name" value = "userInfoDao1"></property>
</bean>
<bean id = "userInfoService" class="com.skymr.spring.test.service.impl.UserInfoServiceBean">
<property name="name" value="skymr"></property>
</bean>
<context:component-scan base-package="springlive.learn.component"/>
<context:annotation-config></context:annotation-config>
</beans>
结果输出如下:
userInfoDao保存一个用户
看,和猜测的一样,当@Autowired装配且有多个类型的bean中,是先装配的名称相同的那个bean, 再进一步,删除userInfoDao的xml配置,打印出的是userInfoDao1,证实@Autowired确定是按类型装配的
总结:
1.@Resource默认按名称装配,找不到与名称相配的Bean时,才会按类型装配
2.@Autowired按类型装配,当有多个相配的类型是,装配相同名称的bean
3.@Autowired(required=true)不允许为null,不然抛出异常
4.@Autowired(required=false)允许为null
5.想让@Autowired按名称装配,与@Qualifier一起使用
为证实第5点,再行测试
@Autowired @Qualifier("userInfoDao1")
private UserInfoDao userInfoDao;