文章目录
Spring依赖注入的方式
Spring依赖注入(DI)有三种方式:
- Setter方法注入
- 构造方法注入
- 基于注解注入
- 静态工厂的方法注入
- 实例工厂的方法注入
1、setter方法注入
最简单的注入方式。
值类型用value注入,引用类型用ref注入。
假设有一个SpringAction,类中需要实例化一个SpringDao对象,那么就可以定义一个private的SpringDao成员变量,然后创建SpringDao的set方法(这是IOC的注入入口)。
package com.bless.springdemo.action;
public class SpringAction {
//注入对象springDao
private SpringDao springDao;
//一定要写被注入对象的set方法
public void setSpringDao(SpringDao springDao) {
this.springDao = springDao;
}
public void ok(){
springDao.ok();
}
}
然后编写spring的xml文件,< bean >标签中的name属性是class属性的一个别名,class属性指类的全名,因为在SpringAction中有一个公共属性SpringDao,所以要在< bean >标签中创建一个< property >标签指定SpringDao。< property >标签中的name就是SpringAction类中的SpringDao的属性名,ref是引用的意思,指下面的< bean name=“springDao” class="">,这样其实是spring将SpringDaoImpl对象实例化并且调用SpringAction的setSpringDao方法将SpringDao注入。
<!--配置bean,配置后该类由spring管理-->
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">
<!--(1)依赖注入,配置当前类中相应的属性-->
<property name="springDao" ref="springDao"></property>
</bean>
<bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>
2、构造器注入
带有参数的构造函数注入。
创建两个变量SpringDao和User,但是并未设置对象的set方法,所以就不能支持第一种注入方式,这里的注入方式是在SpringAction的构造函数中注入,也就是说在创建SpringAction对象时要将SpringDao和User两个参数值传进来。
public class SpringAction {
//注入对象springDao
private SpringDao springDao;
private User user;
public SpringAction(SpringDao springDao,User user){
this.springDao = springDao;
this.user = user;
System.out.println("构造方法调用springDao和user");
}
public void save(){
user.setName("卡卡");
springDao.save(user);
}
}
在xml文件中不用< property >的形势,而是使用< constructor-arg >标签,ref属性指向其他< bean >标签的name属性。
<!--配置bean,配置后该类由spring管理-->
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">
<!--(2)创建构造器注入,如果主类有带参的构造方法则需添加此配置-->
<constructor-arg ref="springDao"></constructor-arg>
<constructor-arg ref="user"></constructor-arg>
</bean>
<bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>
<bean name="user" class="com.bless.springdemo.vo.User"></bean>
解决构造方法参数的不确定性,可能会遇到构造方法传入的两个参数都是同类型的,为了赋值能够对应,有两种处理方式:
1. 设置index参数位置:
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">
<constructor-arg index="0" ref="springDao"></constructor-arg>
<constructor-arg index="1" ref="user"></constructor-arg>
</bean>
2. 设置参数类型:
<constructor-arg type="java.lang.String" ref=""/>
3、基于注解的注入
首先了解一下bean的autowire属性,它有三个属性值:constructor、byName、byType。
- constructor:通过构造方法进行自动注入,spring会会匹配与构造方法参数类型一致的bean进行注入,如果有一个多参数
的构造方法,一个只有一个参数的构造方法,在容器中查找到多个匹配多参数构造方法的bean,那么spring会优先将bean注入
到多参数的构造方法中。
- byName:被注入bean的id名必须与set方法后半截匹配,并且id名称的第一个单词首字母必须小写。
- byType:查找所有的set方法,将符合参数类型的bean注入。
主要有四种注解可以注册bean,每种注解可以任意使用,只是语义上有差异:
@Component:可以用于注册所有bean。
@Repository:主要用于注册dao层的bean。
@Controller:主要用于注册控制层的bean。
@Service:主要用于注册服务层的bean。
描述依赖关系主要有两种:
@Resource:java的注解,默认以byName的方式去匹配与属性名相同的bean的id,如果没有找到就会以byType的方式查找,如果byType查找到多个的话,使用@Qualifier注解(spring注解)指定某个具体名称的bean。
@Resource
@Qualifier("userDaoMyBatis")
private IUserDao userDao;
public UserService(){
@Autowired:spring注解,默认是以byType的方式去匹配与属性名相同的bean的id,如果没有找到,就通过byName的方式去查找。
@Autowired
@Qualifier("userDaoJdbc")
private IUserDao userDao;
4、p名称空间注入(函数注入)
set注入是spring特有,为了简化< property >写法
- applicationContext.xml中< beans >标签头部导入p命名空间
xmlns:p="http://www.springframework.org/schema/p"
- 书写格式:
值类型注入——p:属性名=“值”
引用类型——p:属性名-ref=“引用的< bean >name属性”
把Run类中的name属性值设置为haha,age属性设置为20,引用属性hello引用
<bean name="run2" class="cn.itcats.thread.Run" p:name="haha" p:age="20" p:hello-ref="hello"></bean>
5、spel注入(spring Expression Language spring表达式语言)
<bean name="runSpel" class="cn.itcats.thread.Run">
<!-- 取bean标签中name为"user"中property为"name"中的value值 --!>
<property name="name" value="#{user.name}"></property>
</bean>
SpEL特性:
(1)、使用Bean的ID来引用Bean;
(2)、调用方法和访问对象的属性;
(3)、对值进行算术、关系和逻辑运算;
(4)、正则表达式匹配;
(5)、集合操作
6、静态工厂的方法注入
通过调用静态工厂的方法来获取自己需要的对象,为了让spring管理所有的对象,不能直接通过"工厂类.静态方法()"来获取对象,要通过spring注入的方式获取。
package com.bless.springdemo.factory;
import com.bless.springdemo.dao.FactoryDao;
import com.bless.springdemo.dao.impl.FactoryDaoImpl;
import com.bless.springdemo.dao.impl.StaticFacotryDaoImpl;
public class DaoFactory {
//静态工厂
public static final FactoryDao getStaticFactoryDaoImpl(){
return new StaticFacotryDaoImpl();
}
}
注入一个FactoryDao对象。
public class SpringAction {
//注入对象
private FactoryDao staticFactoryDao;
public void staticFactoryOk(){
staticFactoryDao.saveFactory();
}
//注入对象的set方法
public void setStaticFactoryDao(FactoryDao staticFactoryDao) {
this.staticFactoryDao = staticFactoryDao;
}
}
spring的IOC配置文件,< bean name=“staticFactoryDao” >指向的class并不是FactoryDao的实现类,而是指向静态工厂DaoFactory,并且配置factory-method="getStaticFactoryDaoImpl"指定调用哪个工厂方法:
<!--配置bean,配置后该类由spring管理-->
<bean name="springAction" class="com.bless.springdemo.action.SpringAction" >
<!--(3)使用静态工厂的方法注入对象,对应下面的配置文件(3)-->
<property name="staticFactoryDao" ref="staticFactoryDao"></property>
</bean>
<!--(3)此处获取对象的方式是从工厂类中获取静态方法-->
<bean name="staticFactoryDao" class="com.bless.springdemo.factory.DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>
7、实例工厂的方法注入
获取对象实例的方法不是静态的,所以需要首先new工厂类,在调用普通的实例方法:
public class DaoFactory {
//实例工厂
public FactoryDao getFactoryDaoImpl(){
return new FactoryDaoImpl();
}
}
通过实例工厂类创建FactoryDao对象:
public class SpringAction {
//注入对象
private FactoryDao factoryDao;
public void factoryOk(){
factoryDao.saveFactory();
}
public void setFactoryDao(FactoryDao factoryDao) {
this.factoryDao = factoryDao;
}
}
spring的配置文件:
<!--配置bean,配置后该类由spring管理-->
<bean name="springAction" class="com.bless.springdemo.action.SpringAction">
<!--(4)使用实例工厂的方法注入对象,对应下面的配置文件(4)-->
<property name="factoryDao" ref="factoryDao"></property>
</bean>
<!--(4)此处获取对象的方式是从工厂类中获取实例方法-->
<bean name="daoFactory" class="com.bless.springdemo.factory.DaoFactory"></bean>
<bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean>
复杂类型注入
1、array数组的注入
2、list集合的注入
3、map集合的注入
4、properties的注入
总结
在实际的使用中setter注入和构造函数注入使用的最多。
通过spring创建的对象默认是单例的。想创建多实例对象可以在< bean >标签中添加一个属性scope=prototype
<bean name="..." class="..." scope="prototype">