Spring的核心机制:依赖注入
依赖注入的概念
如果要在一个类中,使用另一个类,传统的方式是直接new:
class A{
//......
B b=new B();
//......
}
A类对象依赖于B类对象,如果没有B类对象,A类对象就不能正常工作,称为A依赖B。
上面的方式会增加A类与B类的耦合,不利于项目后期的升级(扩展)、维护。
在Spring中,B类的实例(被调用者),不再由A类(调用者)创建,而是由Spring容器创建,创建好以后,由Spring容器将B类实例注入A类实例中,称为依赖注入(Dependency Injection,DI)。
原本是由A类主动创建B类对象(A类控制B类的创建),现在是Spring容器创建B类对象,注入A类对象中,A类被动接受Spring容器创建的B类实例,B类对象创建的控制权发生了反转,所以又叫做控制反转(Inversion of Control,IoC)。
控制反转(IoC)是由依赖注入(DI)实现的,依赖注入又是由spring容器实现的,所以Spring容器又叫做Spring IoC容器。。
依赖注入是一种优秀的解耦方式,由Spring容器负责控制类(Bean)之间的关系,降低了类之间的耦合。
常用的方式有2种:
- 设值注入,也叫set方式注入
- 构造方法注入
设值注入
将依赖作为成员变量,通过主调类的setter方法注入依赖。
public class A {
private B b;
public void setB(B b) {
this.b = b;
}
//......
}
xml配置:
<bean name="b" class="com.chy.bean.B" />
<bean name="a" class="com.chy.bean.A">
<property name="b" ref="b"/>
</bean>
使用<property>注入依赖,name指定属性名(成员变量名),ref指定要注入的bean(value指定要注入的常量值)。
如果要注入多个依赖,使用多个<property />即可。
构造方法注入
将依赖作为成员变量,通过主调类的构造方法注入依赖。
public class A {
private B b;
public A(B b) {
this.b = b;
}
//......
}
xml配置:
<bean name="b" class="com.chy.bean.B" />
<bean name="a" class="com.chy.bean.A">
<constructor-arg name="b" ref="b" />
</bean>
一个<constructor-arg />注入一个参数,name指定构造方法中的形参名,ref指定要注入的bean(value指定要注入的常量值)。
形参可用 name="形参名" 指定,也可以使用 index="形参表下标" 来指定(第一个参数 => 下标0)。
如果有多个形参,使用多个<constructor-arg />即可,spring会调用对应的构造方法。
不管是设值注入,还是构造方法注入,都是将依赖作为成员变量,所以有时候也把注入依赖叫做注入属性。
依赖可分为3种类型:
- 注入int、float、String之类的基本数据类型,使用value。
比如根据学号查学生信息,需要注入一个int型的学号。
spring会自动将值转换为需要的类型,比如需要的String,value="chy"会以String的形式注入。value="1",如果需要的是int,就转换为int注入,如果需要的是String,就转换为String注入。
- 注入其他Bean的实例,使用ref。
- 注入数组、集合、Properties等复杂类型
注入复杂类型的依赖
将复杂类型的数据数据作为成员变量:
private Object[] arr;
private List<Object> list;
private Set<Object> set;
private Map<String,Object> map;
private Properties properties;
设值注入需提供对应的setter方法,构造方法注入需提供对应的构造方法。
设值注入:
<bean name="a" class="com.chy.bean.A">
<!-- 注入数组-->
<property name="arr">
<array>
<!-- 基本数据类型使用value,bean的实例使用ref,可嵌套其他复杂类型-->
<value>chy</value>
<ref bean="b" />
</array>
</property> <!-- 注入List -->
<property name="list">
<list>
<value>chy</value>
<ref bean="b" />
</list>
</property> <!-- 注入Set -->
<property name="set">
<set>
<value>chy</value>
<ref bean="b" />
</set>
</property> <!-- 注入Map-->
<property name="map">
<map>
<!-- Map的key只能是String,基本数据类型用value,其他Bean的实例用value-ref -->
<entry key="id" value="1" />
<entry key="user" value-ref="b" />
</map>
</property> <!-- 注入Properties -->
<property name="properties">
<props>
<!-- 键、值都只能是String -->
<prop key="username">chy</prop>
<prop key="password">abcd</prop>
</props>
</property>
</bean>
<property name=""> name指定属性名(成员变量名)。
数组、List、Set的配置方式是差不多的。
构造方法注入:
<constructor-arg name="arr">
<array>
<value>chy</value>
<ref bean="b" />
</array>
</constructor-arg>
配置方式和设值注入差不多,只不过将 property 换为 constructor-arg ,name是指定形参名。
用的最多的是设值注入,因为很多时候都要修改成员变量的值,setter方法一般都要写,直接用setter方法设值注入,没必要再写带参的构造方法。
使用自动装配注入其它Bean的实例
原先注入其它bean的实例,需要使用<property />或<constructor />注入。
使用自动装配后,不需要使用<property />、<constructor />,spring会自动在容器中找到满足要求的其它bean,注入进来。
<bean name="a" class="com.chy.bean.A" autowire="byName" />
可选的值:
- no 默认值,不使用自动装配,如果要注入其它bean的实例,需要使用<property />或<constructor />。
- byName 根据name来自动装配
- byType 根据type来自动装配
- constructor 根据构造函数形参类型进行byType方式的自动装配
- default 使用全局默认的自动装配方式。
byName和byType都能在设值注入中使用,constructor只能在构造方法注入中使用。
byName
public class A {
private B b;
public void setB(B b) {
this.b = b;
}
}
<bean name="b" class="com.chy.bean.B" />
<bean name="a" class="com.chy.bean.A" autowire="byName" />
A依赖B,A中有对应的setter方法。
byName,name就是setter方法的方法名,去掉set,后面部分使用camel写法,比如setB() => b,
spring会自动到容器中找到name="b"的bean,注入。
name="b"的bean只能有一个,不然spring不知道要注入哪个。
byType
和byName差不多,也是要配合setter方法使用。不同的是:
byType,type是形参表的参数类型。比如setB(B b),参数类型是B,Spring自动找到class=“B”的bean,注入。
class=“B”的bean只能有一个,不然spring不知道要注入哪个。
constructor
public class A {
private B b;
public A(B b) {
this.b = b;
}
}
顾名思议,需要和构造方法注入搭配使用。
找到带参的构造器,根据参数类型,按照byType的方式注入依赖。
default
使用全局默认的自动装配方式。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"
default-autowire="byName"> <bean name="b" class="com.chy.bean.B" />
<bean name="a" class="com.chy.bean.A" autowire="default" />
</beans>
需要在根元素<beans>中设置全局默认的自动装配方式,所有default方式的自动装配都是使用 default-autowire 设置的方式进行装配。
自动装配的贪婪原则
自动装配会尽量多地注入依赖。
比如constructor ,有2个构造方法:(B b)、(B b, C c),如果容器中有B、C的实例,则优先调用(B b, C c),会尽量多地注入依赖。
自动装配的优点:一个属性就搞定,不必写大量的<property />或<constructor />。
缺点:自动装配只能注入其它bean的实例,使用时有限制条件。(可以和注入基本类型、复杂类型的方式一起使用。实际上,注入基本类型、bean的实例、复杂类型都可以搭配使用。)
使用SpEL注入依赖
SpEL,即Spring Expression Language,spring表达式语言。
使用SpEL可以注入基本类型,可以注入其它Bean,可以访问其它Bean的成员变量、调用其它Bean中的方法。
使用示例:
<bean name="score" class="com.chy.bean.Score">
<property name="chinese" value="#{90}" />
<property name="math" value="#{100}" />
<property name="english" value="#{95}" />
</bean>
<bean name="student" class="com.chy.bean.Student">
<property name="no" value="#{1}" />
<property name="name" value="#{'chy'}" />
<property name="score" value="#{score}" />
</bean>
SpEL放在#{ }中,数值型直接写,字符、字符串要加单引号,可以直接引用其它Bean。
SpEL使用的是设值注入,所以需要提供setter方法,只能用<property />注入值,不能使用构造方法注入。
不管值是什么类型,都只能用value,不能用ref。
可以直接访问其它Bean的成员变量,比如 #{score.math} ,实质是调用对应的getter方法,所以需要提供getter方法。
可以调用其它Bean的方法,比如 #{score.getMath()},如果该方法返回void,作为null处理。
Spring的核心机制:依赖注入的更多相关文章
- Spring的核心机制依赖注入
原文地址:http://developer.51cto.com/art/200610/33311.htm 本文主要讲解依赖注入(设值注入.构造注入),作用是可以使Spring将各层的对象以松耦合的方式 ...
- Spring的核心机制——依赖注入(Dependency Inject)
Spring不仅提供对象,还提供对象的属性值,而不是由使用该对象的程序所提供的. Java应用是由一些相互协作的对象所组成的,在Spring中这种相互协作的关系就叫依赖关系. 如果A组件调用了B组件的 ...
- Spring的核心机制——依赖注入(Dependency Inject)
Spring不仅提供对象,还提供对象的属性值,而不是由使用该对象的程序所提供的. Java应用是由一些相互协作的对象所组成的,在Spring中这种相互协作的关系就叫依赖关系. 如果A组件调用了B组件的 ...
- spring-第一篇之spring核心机制依赖注入(DI)/控制翻转(IoC)
1.spring的核心机制:依赖注入(DI)/控制翻转(IoC) 什么是依赖:A对象需要调用B对象,所以A依赖于B. 什么是注入:A对象注入一个属性B对象. 什么是依赖注入(DI):A对象依赖于B对象 ...
- 7 -- Spring的基本用法 -- 3... Spring 的核心机制 : 依赖注入
7.3 Spring 的核心机制 : 依赖注入 Spring 框架的核心功能有两个. Spring容器作为超级大工厂,负责创建.管理所有的Java对象,这些Java对象被称为Bean. Spring容 ...
- Spring源码剖析依赖注入实现
Spring源码剖析——依赖注入实现原理 2016年08月06日 09:35:00 阅读数:31760 标签: spring源码bean依赖注入 更多 个人分类: Java 版权声明:本文为博主原 ...
- 回客科技 面试的 实现ioc 容器用到的技术,简述BeanFactory的实现原理,大搜车面试的 spring 怎么实现的依赖注入(DI)
前言:这几天的面试,感觉自己对spring 的整个掌握还是很薄弱.所以需要继续加强. 这里说明一下spring的这几个面试题,但是实际的感觉还是不对的,这种问题我认为需要真正读了spring的源码后说 ...
- AspNet Core 核心 通过依赖注入(注入服务)
说起依赖注入 相信大家已经很熟悉了,这里我在简要的描述一遍, 什么是依赖注入: 我们从字面意义上来解释一下:依赖代表着两个或者多个对象之间存在某些特定的联系:举一个不是很恰当的例子 比如说一度夫妻组成 ...
- Spring quartz Job不能依赖注入,Spring整合quartz Job任务不能注入
Spring quartz Job不能依赖注入,Spring整合quartz Job任务不能注入 Spring4整合quartz2.2.3中Job任务使用@Autowired不能注入 >> ...
- spring 控制反转与依赖注入原理-学习笔记
在Spring中有两个非常重要的概念,控制反转和依赖注入:控制反转将依赖对象的创建和管理交由Spring容器,而依赖注入则是在控制反转的基础上将Spring容器管理的依赖对象注入到应用之中: 所谓依赖 ...
随机推荐
- H3C交换机如何删除VLAN
H3C交换机如何删除VLAN,如果直接使用“undo vlan”是删不干净的,因为配置VLAN时还配置过接口. 1.首先通过console口或telnet连接三层交换机,进入用户视图模式”<H3 ...
- Xamarin.FormsShell基础教程(2)创建Shell解决方案
Xamarin.FormsShell基础教程(2)创建Shell解决方案 创建Shell解决方案 在开发Shell的应用程序时,首先需要创建一个Shell解决方案,其具体操作步骤如下: (1)在VS的 ...
- 【PHP】使用phpoffice/phpspreadsheet导入导出数据
当你在使用phpoffice/phpexcel 类库时候.composer 会给你提示一句话 Package phpoffice/phpexcel is abandoned, you should a ...
- matlab学习笔记12_3串联结构体,按属性创建含有元胞数组的结构体,filenames,isfield,isstruct,orderfields
一起来学matlab-matlab学习笔记12 12_3 结构体 串联结构体,按属性创建含有元胞数组的结构体,filenames,isfield,isstruct,orderfields 觉得有用的话 ...
- chrome 报错 ERR_CERT_AUTHORITY_INVALID
场景: 本地调试https/wss程序,使用了openssl自签名的证书,解决方法:添加到信任证书 根据以下图片流程操作 然后 打开selfsigned.cer 清空该网站缓存 参考资料: https ...
- Windows10 下安装 oracle 客户端,安装 plsql 破解并实现汉化
一,软件准备 1,win10 操作系统 2,oracle_11g_r2 client 这里是 64 位的软件 3, plsql 11.0.6 这里我们下载 64 的,32 位操作系统现在已经很少了, ...
- 使用BaGet 搭建私有nuget 服务器
使用BaGet 搭建私有nuget 服务器 netNugetBaGet 引言 为了增强代码的安全性和企业团队开发的高效性,搭建私有的package 包管理服务器是很有必要的,搭建私有的类库管理服务有以 ...
- Node 脚本的调试工具
2016年,Node 决定将 Chrome 浏览器的"开发者工具"作为官方的调试工具,使得 Node 脚本也可以使用图形界面调试 1.准备 创建目录 D:\nodejs>mk ...
- git中配置的.gitignore不生效的解决办法
通常我们希望放进仓库的代码保持纯净,即不要包含项目开发工具生成的文件,或者项目编译后的临时文件.但是,当我们使用git status查看工作区状态的时候,总会提示一些文件未被track.于是,我们想让 ...
- ActiveMQ 安装方法
1. 打开浏览器,访问网址 http://activemq.apache.org/components/classic/download/ ,下载最新的版本,当前最新版本为5.15.9,根据Activ ...