详解 Spring 框架的依赖注入

本篇主要介绍 Spring 的依赖注入。依赖注入是 Spring 协调不同 Bean 实例之间的合作而提供的一种工作机制,在确保 Bean 实例之间合作的同时,并能保持每个 Bean 的相对独立性。通过本篇的学习,可以达成如下目标。

● 理解基于构造函数的依赖注入

● 理解基于设置函数的依赖注入

● 基于自动装配的依赖注入

● 基于注解的依赖注入

在 Spring 框架下,当 Bean 实例 A 运行过程中需要引用另外一个 Bean 实例 B 时,Spring 框架会创建 Bean 的实例 B,并将实例 B 通过实例 A 的构造函数、set 方法、自动装配和注解方式注入到实例 A,这种注入实例 Bean 到另外一个实例 Bean 的过程称为依赖注入。

在课程案例 SpringProgram 项目中,事务组件类 EmailNotice 内部引用了实体类 Teacher 类,用于向 Teacher 类发送消息,因此 EmailNotice 类依赖于 Teacher 类。Spring IOC 容器会在创建 EmailNotice 类和 Teacher 类的实例后,将 Teacher 类的实例注入到 EmailNotice 类的实例中。

依赖注入的好处就是尽可能隔离 Bean 之间的代码耦合,提高 Bean 重用的可能性,并尽量降低程序代码的维护难度。Spring 框架通过依赖注入技术将不同的 Bean 融合起来,完成复杂业务操作,但又确保了每个 Bean 相对的独立性。

Spring 框架提供了构造函数注入、设置方法注入、自动装配注入和注解注入四种注入方式,下面分别进行讨论并说明。

1、 基于构造函数的依赖注入

构造函数注入就是通过 Bean 类的构造方法,将 Bean 所依赖的对象注入。构造函数的参数一般情况下就是依赖项,spring 容器会根据 bean 中指定的构造函数参数来决定调用那个构造函数。

在课程案例 SpringProgram 项目中新建发送通知组件类 ShortNotice 类,代码如下:

ShortNotice 类依赖实体 Teacher 类,由 ShortNotice 类的构造函数注入。

在课程案例 SpringProgram 项目的 config 目录下新建 structure.xml 配置文件,配置文件代码如下:

构造注入可以传入简单值或对象类型,注入参数使用 <constructor-arg> 标签。如果注入不止一个参数时,当把参数传递给构造函数时,可能会存在歧义。要解决这个问题,就要确保在构造函数定义的参数顺序,与在配置文件中定义的注入参数顺序一致。

例如,下面的类

在配置文件需要做如下定义:

在配置文件中,也可以使用 type 属性显式指定构造函数参数的类型,容器允许使用与简单类型匹配的类型。

例如,下面的类

配置文件可以做如下定义:

另外,使用构造函数注入需要注意的是,如果需要向一个对象传递一个引用,需要使用标签的 ref 属性,如果需要直接传递值,那么应该使用如上所示的 value 属性。

2、基于设置函数的依赖注入

将 Bean 所依赖的对象通过设置函数注入,Bean 需要为注入的依赖对象提供设置方法。

在课程案例 SpringProgram 项目中,发送通知组件类 EmailNotice 依赖实体类 Teacher,向 Teacher 类发送消息。EmailNotice 类提供了设置 Teacher 类的方法,Spring IOC 容器创建 EmailNotice 和 Teacher 实例后,调用 EmailNotice 类设置 Teacher 类的方法,将 Teacher 实例注入到 EmailNotice 实例。EmailNotice 类代码如下:

EmailNotice 类有值属性和对象引用属性,值属性为 message,对象引用属性为 teacher。值属性可以通过 value 注入,对象引用属性需要通过 ref 注入。注入标签使用 <property>。配置文件代码如下。

Spring IOC 容器除了向 Bean 注入简单对象外,也可以向 Bean 注入集合对象。如 map、list、set、数组等集合对象。

在课程案例 SpringProgram 项目中新建实体类 Student,Student 类有 info 和 courses 两个属性,info 是 Map 对象,用于记录学生的基本信息,courses 是 List 对象,用于记录学生学习的课程名称。

Spring 配置文件的注入代码如下。

3、基于自动装配的依赖注入

前面讨论了基于构造函数的依赖注入和基于设置函数的依赖注入。了解了在 Spring 配置文件中使用 <constructor-arg> 和 < property > 标签注入 Bean 的依赖对象。Spring 容器还可以在不使用 < constructor-arg > 和 < property> 标签的情况下自动装配相互协作的 bean 之间的关系,这有助于减少在 Spring 配置文件中编写大量的注入语句。

Spring 的自动装配有三种模式:byType (类型模式),byName (名称模式)、constructor (构造函数模式)。

在 byType 模式中,Spring IOC 容器会基于反射查看 Bean 定义的类。当 Spring 容器发现 Bean 被设置为自动装配的 byType 模式后,它会根据参数类型在 Spring 容器中查找与参数类型相同的被依赖 Bean 对象,如果已经创建,则会把被依赖的对象自动注入到 Bean 中,如果没有创建,则不会注入。注入过程需要借助 Bean 提供的设置方法来完成,否则注入失败。

在课程案例 SpringProgram 项目中,EmailNotice 类代码如下:

EmailNotice 类依赖于 Teacher 类,并提供了设置 Teacher 类的 set 方法,可以使用 Spring 的自动装配机制。配置文件代码如下:

配置文件通过使用 <bean> 的 autowire 属性启动名称为 eamilNotice 的自动装配功能。

在 byName 模式中,Spring IOC 容器会根据定义 Bean 类的属性名称,在 Spring 容器中查找与 Bean 类属性名称相同的其它 Bean 名称进行匹配,如果找到则注入依赖 bean。

类似于 byName 和 byType 模式,constructor (构造函数模式) 适用于构造函数参数类型,Spring IOC 容器会根据定义 Bean 类的构造函数给出的参数类型,在 Spring 容器中查找与其类型相匹配的其它 Bean 类,如果找到则注入依赖 Bean。

自动装配最大的问题在于匹配失败后,Spring 容器将不会向 Bean 注入任何依赖对象,就会导致 Bean 获取不到所依赖的对象,当 Bean 使用该依赖对象时,就会发生错误。因此,在可能的情况下尽可能使用手动装配。

4、基于注解的依赖注入

前面依赖注入都需要在配置文件中手动配置,当需要配置较多 Bean 类时,需要做大量的手动部署工作,这显然不妥。在 Spring2.5 之后,Spring 增加了注解方式注入,可以解决较多 Bean 类依赖注入的问题。

Spring 主要提供了 @Autowired 和 @Resource 注解模式,下面也重点讨论这两种注解模式。

@Autowired 注解,可以对 Bean 类成员变量、方法及构造函数进行标注,完成依赖注入的自动装配工作。使用 @Autowired 可以省略 Bean 类的待依赖注入对象的 set 方法,@Autowired 默认情况下按照依赖注入对象的类型自动进行匹配。加入 @Autowired 注解的方式是在 Bean 类依赖注入对象的前面加上 @Autowired 语句。

例如,在课程案例 SpringProgram 项目中新建发送通知类 QqNotice,QqNotice 类依赖 Teacher 类,在声明 Teacher 类变量的前面加上 @Autowired 语句,代码如下:

使用注解前必须在 Spring 配置文件中注册注解驱动 <context:annotation-config/>,这样注解才能被正确识别。

使用 @Autowired 注解后,只需要在配置文件中定义 Bean 就可以了,无需再配置 Bean 之间的关联关系。

测试代码如下:

@Autowired 还提供 required 的属性,用来处理当注入的 Bean 实例不存在的情况。required 为 true 时,如果注入的 Bean 实例不存在,程序会抛出异常;required 为 false 时,如果注入的 Bean 实例不存在,程序会忽略。由于默认情况下 @Autowired 是按类型匹配的 (byType),如果需要按名称 (byName) 匹配,可以使用 @Qualifier 注解与 @Autowired 结合。

例如,修改 QqNotice 类,加入 @Qualifier 注解 @Qualifier ("teacher"),Spring 容器将会在容器中注册的所有 Bean 实例中查找名称为 “teacher” 的 Bean 实例并注入,“teacher” 为在 Spring 配置文件中定义 Bean 类的名称。

@Resource 注解的功能和 @Autowired 注解功能相近,@Resource 有 name 和 type 两个主要的属性。Spring 容器对于 @Resource 注解的 name 属性解析为 bean 的名字,type 属性则解析为 bean 的类型。因此使用 name 属性,则按 byName 模式的自动注入策略,如果使用 type 属性则按 byType 模式自动注入策略。如果两个属性都未指定,Spring 容器将通过反射技术默认按 byName 模式注入。

例如下面的注解声明:

课程小结

本文介绍了 Spring 提供的四种依赖注入方式,分别是基于构造函数的依赖注入、基于设置函数的依赖注入、基于自动装配的依赖注入、基于注解的依赖注入。

基于构造函数的依赖注入。Bean 类依赖外部类时,可以在 Bean 类内部声明该依赖类,并在提供的构造函数参数中声明该类。Spring 创建 Bean 实例时,Spring 容器会根据 Bean 中指定的构造函数参数注入外部类。

基于设置函数的依赖注入。Bean 类依赖外部类时,可以在 Bean 类内部声明该依赖类,并提供该设置该依赖类的 set 方法。Spring 容器会根据 Bean 类提供的 set 方法,将外部依赖类注入到 Bean 中。

基于自动装配的依赖注入。该模式自动装配相互协作的 bean 之间的关系,Spring 的自动装配有三种模式:byType (类型模式),byName (名称模式)、constructor (构造函数模式)。Spring 的自动装配有助于减少在 Spring 配置文件中编写大量的注入语句。

基于注解的依赖注入。在 Spring2.5 之后,Spring 增加了注解注入。当 Bean 类依赖外部类时,只要对 Bean 类所依赖的类成员变量、方法及构造函数进行标注,Spring 即可完成依赖注入的自动装配工作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值