3.Spring-依赖注入(DI)

Dependency Injection(DI)

依赖注入(Dependency Injection,简称DI)是指通过外部容器在对象之间建立依赖关系的一种方式。

简单说:就是由 IOC 容器在运⾏期间,动态地将某种依赖关系注⼊到对象之中。

与控制反转是同一个概念,或者依赖注入是实现控制反转的一种常见方式。

IOC是一种思想 而依赖注入是 IOC的一种实现。

依赖注入的作用:在容器初始化对象时,把对象的属性进行赋值,处理对象之间的依赖关系

依赖注入

1.设值注入

本质上是调用 类提供的属性的setter方法 进行属性赋值

XML 复制代码
<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.构造注入

本质上是调用 类的 有参的构造方法 进行属性的初始化

XML 复制代码
<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()进行属性的初始化

XML 复制代码
<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
java 复制代码
@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
java 复制代码
@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的耦合。

相关推荐
程序员爱钓鱼7 分钟前
Python编程实战 · 基础入门篇 | 推导式(列表推导式 / 字典推导式)
后端·python
无限进步_8 分钟前
【C语言】函数指针数组:从条件分支到转移表的优雅进化
c语言·开发语言·数据结构·后端·算法·visual studio
程序员爱钓鱼10 分钟前
Python编程实战 · 基础入门篇 | 循环控制:break / continue / else
后端
Rocket MAN17 分钟前
Spring Boot 缓存知识体系大纲
spring boot·spring
canonical_entropy22 分钟前
领域驱动设计(DDD)领域对象一定要讲究充血模型吗?
后端·领域驱动设计·graphql
想睡好31 分钟前
express中间件(java拦截器)
java·中间件·express
兢兢业业的小白鼠34 分钟前
Java常用中间件整理讲解——Redis,RabbitMQ
java·中间件·java-rabbitmq·1024程序员节
鱼儿也有烦恼38 分钟前
快速学完 LeetCode top 1~50 [特殊字符]
java·算法·leetcode·1024程序员节
独自破碎E39 分钟前
LeetCode 380: O(1) 时间插入、删除和获取随机元素
java·算法·leetcode
信仰_27399324342 分钟前
Mybatis一级缓存
java·缓存·mybatis