Dependency Injection(DI)
依赖注入(Dependency Injection,简称DI)是指通过外部容器在对象之间建立依赖关系的一种方式。
简单说:就是由 IOC 容器在运⾏期间,动态地将某种依赖关系注⼊到对象之中。
与控制反转是同一个概念,或者依赖注入是实现控制反转的一种常见方式。
IOC是一种思想 而依赖注入是 IOC的一种实现。
依赖注入的作用:在容器初始化对象时,把对象的属性进行赋值,处理对象之间的依赖关系
依赖注入
1.设值注入
本质上是调用 类提供的属性的setter方法 进行属性赋值
<bean name="user" class="com.rimi.bean.User">
<property name="username" value="admin"></property>
<property name="password" value="123456"></property>
</bean>
- name 代表 属性的名字(因为 spring容器会根据属性名去找对应的setter方法,所以 命名规范)
- value 代表的属性的值
2.构造注入
本质上是调用 类的 有参的构造方法 进行属性的初始化
<bean name="user" class="com.rimi.bean.User">
<constructor-arg name="username" value="admin"></constructor-arg>
<constructor-arg name="password" value="123456"></constructor-arg>
<constructor-arg name="userid" value="1"></constructor-arg>
</bean>
使用构造注入时,bean中的 constructor-arg 的数目必须和 构造方法中 形参的数目一致
constructor-arg
- name 代表的是形参的名字
- value 形参的值
- index 表示形参的编号
- type 指定形参的类型。
使用方式:通常以设值注入为主,构造注入为辅。对于依赖关系不需要发生改变的注入,通常使用构造注入。
3.自动装配注入
本质上是调用 类的属性的 byType(类型模式),byName(名称模式)、constructor(构造函数模式),autodetect()进行属性的初始化
<bean name="user" autowire="byType" class="com.rimi.bean.User">
<property name="username" value="admin"></property>
</bean>
no
: 不使用自动装配。Bean依赖必须通过ref元素定义。这是默认配置,在较大的部署环境中不鼓励改变这个配置,显式配置合作者能够得到更清晰的依赖关系。byName
: 根据setter方法名进行自动装配。Spring容器查找容器中全部Bean,找出其id与setter方法名去掉set前缀,并小写首字母后同名的Bean来完成注入。如果没有找到匹配的Bean实例,则Spring不会进行任何注入。byType
: 根据setter方法的形参类型来自动装配。Spring容器查找容器中的全部Bean,如果正好有一个Bean类型与setter方法的形参类型匹配,就自动注入这个Bean;如果找到多个这样的Bean,就抛出一个异常;如果没有找到这样的Bean,则什么都不会发生,setter方法不会被调用。constructor
: 与byType类似,区别是用于自动匹配构造器的参数。如果容器不能恰好找到一个与构造器参数类型匹配的Bean,则会抛出一个异常。autodetect
: Spring容器根据Bean内部结构,自行决定使用constructor或byType策略。如果找到一个默认的构造函数,那么就会应用byType策略。
4.注解注入
@Autowired
@Service
public class UserServiceImpl implements UserService{
@AutoWired
private UserDao userDao;
}
内部等同于
@Service
public class UserServiceImpl implements UserService{
@AutoWired(required=true)
private UserDao userDao;
}
同样也可以指定类型byNmae
@Service
public class UserServiceImpl implements UserService{
@AutoWired(required=false)
@Qualifier("userDao")
private UserDao userDao;
}
@Resource
@Service
public class UserServiceImpl implements UserService{
@Resource
private UserDao userDao;
}
内部等同于
@Service
public class UserServiceImpl implements UserService{
@Resource(name="userDao")
private UserDao userDao;
}
同样也可以指定类型byType
@Service
public class UserServiceImpl implements UserService{
@Resource(type=com.edu.dao.UserDao.class)
private UserDao userDao;
}
- @Resource:用于依赖注入,注入的bean的名字 默认和对应的属性名一样即属性名为userDao @Resource(name="bean名字")来进行注入 使用@Resource进行注入,实现原理反射机制,所以即使属性没有set方法 或者构造方法,依然可以注入成功. 对于@Resource注解,如果没有指定注入的bean的名字,并且存在两个相同接口(类型)的bean,则会抛出异常。
- @Autowired:用于依赖注入,默认以byType进行自动装配,当Spring容器中有 相同类型的bean的时候,会自动的注入到私有属性,如果容器里存在两个相同接口(类型的)bean 则会抛出异常
@autowired和@resource注解的区别?
- @Autowired与@Resource都可以用来装配bean,都可以写在字段或setter方法上
- @Autowired默认按类型装配,默认情况下必须要求依赖对象存在,如果要允许null值,可以设置它的required属性为false。如果想使用名称装配可以结合@Qualifier注解进行使用。
- @Resource,默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行名称查找。如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
推荐使用@Resource注解在字段上,这样就不用写setter方法了,并且这个注解是属于J2EE的,减少了与Spring的耦合。