前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring框架入门(三):依赖注入和控制反转

Spring框架入门(三):依赖注入和控制反转

作者头像
sr
发布2019-05-23 17:53:01
5310
发布2019-05-23 17:53:01
举报
文章被收录于专栏:swag code

依赖注入和控制反转概念

依赖注入(IoC) 和 控制反转(DI) 有什么关系呢?其实它们是同一个概念的不同角度描述。

依赖注入(Dependency injection)

是指应用在运行期,由外部容器(Spring容器)动态地将依赖对象注入到另一个对象中。

理解 DI 的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”:

  • 谁依赖于谁:当然是某个容器管理对象依赖于 IoC 容器;“被注入对象的对象”依赖于“依赖对象”;
  • 为什么需要依赖:容器管理对象需要 IoC 容器来提供对象需要的外部资源;
  • 谁注入谁:很明显是 IoC 容器注入某个对象,也就是注入“依赖对象”;
  • 注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。

控制反转(Inversion Of Control)

IoC 容器就是具有依赖注入功能的容器,IoC 容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。应用程序无需直接在代码中 new 相关的对象,应用程序由 IoC 容器进行组装。

在传统模式下通常有两种做法:

  • 原始做法: 调用者主动创建被依赖对象,然后再调用被依赖对象的方法。
  • 简单工厂模式: 调用者先找到被依赖对象的工厂,然后主动通过工厂去获取被依赖对象,最后再调用被依赖对象的方法。

Spring容器的依赖注入

  • 设值注入:是指IoC容器通过成员变量的setter方法来注入被依赖对象。这种注入方式简单、直观,因而在Spring的依赖注入里大量使用。
  • 构造注入:利用构造器来设置依赖关系的方式,被称为构造注入。通过构造器参数对成员变量执行初始化,驱动Spring在底层以反射方式执行带指定参数的构造器。

注意: 建议采用设值注入为主,构造注入为辅的注入策略。对于依赖关系无须变化的注入,尽量采用构造注入;而其他依赖关系的注入,则考虑采用设值注入。

实例

代码语言:javascript
复制
<!-- 通过property属性注入(必须提供set方法) -->
<bean id="user" class="cn.sr.spring.javabean.User">
	<property name="name" value="张三"></property>
	<property name="password" value="123456"></property>
</bean>

<!-- 通过构造函数注入 -->
<bean id="user" class="cn.sr.spring.javabean.User">
	<constructor-arg name="name" value="张三"></constructor-arg>
	<constructor-arg name="password" value="123456"></constructor-arg>
</bean>

//除此之外还可以注入集合类型的对象,List、Set、Map、Properties……

Spring容器中的Bean

对于开发者来说,开发者使用Spring框架主要是做两件事:①开发Bean;②配置Bean。对于Spring框架来说,它要做的就是根据配置文件来创建Bean实例,并调用Bean实例的方法完成”依赖注入”——这就是所谓IoC的本质。

容器中Bean的作用域

当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。Spring支持如下五种作用域:

  • singleton: 单例模式,在整个Spring IoC容器中,singleton作用域的Bean将只生成一个实例。
  • prototype: 每次通过容器的getBean()方法获取prototype作用域的Bean时,都将产生一个新的Bean实例。
  • request: 对于一次HTTP请求,request作用域的Bean将只生成一个实例,这意味着,在同一次HTTP请求内,程序每次请求该Bean,得到的总是同一个实例。只有在Web应用中使用Spring时,该作用域才真正有效。
  • session:该作用域将 bean 的定义限制为 HTTP 会话。 只在web-aware Spring ApplicationContext的上下文中有效。
  • global session: 每个全局的HTTP Session对应一个Bean实例。在典型的情况下,仅在使用portlet context的时候有效,同样只在Web应用中有效。

配置格式如下:

代码语言:javascript
复制
<bean id="…" class="…" scope="singleton"></bean>

如果不指定Bean的作用域,Spring默认使用singleton作用域。prototype作用域的Bean的创建、销毁代价比较大。而singleton作用域的Bean实例一旦创建成果,就可以重复使用。因此,应该尽量避免将Bean设置成prototype作用域。

创建Bean的3种方式

  1. 使用构造器创建Bean实例: 需要提供无参数的构造器,Spring对Bean实例的所有属性执行默认初始化,即所有的基本类型的值初始化为0或false;所有的引用类型的值初始化为null。
  2. 使用静态工厂方法创建Bean: class属性须指定静态工厂类,使用factory-method属性来指定静态工厂方法,如果静态工厂方法需要参数,则使用<constructor-arg…/>元素指定静态工厂方法的参数。
代码语言:javascript
复制
<bean id="user" class="cn.sr.spring.javabean.UserFactory" factory-mothod="getUser">
	<constructor-arg name="name" value="张三"></constructor-arg>
</bean>
代码语言:javascript
复制
package cn.sr.spring.javabean;

public class UserFactory {
	//对应factory-method
	public static void getUser(String name) {
		System.out.println("这是"+name);
	}
}
  1. 使用实例工厂方法创建Bean:
  • factory-bean指定工厂实例
  • factory-method指定实例工厂的工厂方法。
  • 若调用实例工厂方法时需要传入参数,则使用<constructor-arg…/>元素确定参数值。
代码语言:javascript
复制
<bean id="userFactory" class="cn.sr.spring.javabean.UserFactory" />
//此时getUser方法应为非静态
<bean id="user" factory-bean="userFactory" factory-mothod="getUser">
	<constructor-arg name="name" value="张三"></constructor-arg>
</bean>

Bean的生命周期

这里简单的说明一下,对于作用域为prototype的Bean,Spring在仅仅负责创建Bean,每当容器创建Bean后就交给客户端的代码进行维护。但是对应singlton作用域的Bean,Spring会进行创建一次,然后整个容器中共享。所以Spring容器会负责进行跟踪其状态,负责依赖的注入和依赖实例的分配。


结尾

本文只是做简单介绍,个人理解方面偏多,更多有关于IOC和DI以及Bean对象的详解介绍请自行查找相关资料!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 依赖注入(Dependency injection)
  • 控制反转(Inversion Of Control)
    • 在传统模式下通常有两种做法:
      • Spring容器的依赖注入
        • 实例
        • Spring容器中的Bean
          • 容器中Bean的作用域
            • 配置格式如下:
          • 创建Bean的3种方式
            • Bean的生命周期
            • 结尾
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档