Spring学习(十八)Bean 的三种依赖注入方式介绍
依赖注入:让调用类对某一接口实现类的依赖关系由第三方注入,以移除调用类对某一接口实现类的依赖。
接下来将详细的向大家介绍Spring容器支持的三种依赖注入的方式以及具体配置方法:
• 属性注入方法
• 构造函数注入方法
• 工厂方法注入方法
一.属性注入
属性注入即通过setXXX()方法注入Bean的属性值或者依赖对象,由于属性注入方式具有可选择性和灵活高的优点,因此属性注入是实际中最常采用的注入方式。
Spring首先会调用bean的默认构造函数实例化bean对象,然后再通过反射的方法来调用set方法来注入属性值。
属性注入要求bean提供一个默认的构造函数,并且得为需要注入的属性提供set方法。
注意:所谓默认构造函数是指不带参的构造函数
JAVA中定义:
如果类中没有定义任何的构造函数,则JAVA虚拟机自动为其生成一个默认的构造函数。反之,如果类中显式的定义了构造函数,则JAVA虚拟机便不会在为其生成构造函数。
来看一段java示例代码:
Public class Car {
private String brand;
public void setBrand(String brand) {
this.brand = brand;
}
public String getBrand() {
return this.brand;
}
}
可以看到Car这个类有一个String类型的brand属性,并为其提供了setter和getter方法。
我们再来看看与之相对应的属性注入配置文件:
<bean id=“car” class=“com.jike.***.Car” >
<property name=“brand”>
<value>奔驰</value>
</property>
</bean>
其中每一个属性值对应一个property标签,name为属性的名称。
在bean实现类中拥有与其对应的实现方法setBrand()。
注意:Spring只会检查bean中是否有setter方法,而是否有对应的属性变量则不做具体要求,但按照约定俗成的规则我们最好为其设定相应的属性变量。
补充: Spring <property>元素的命名规范:
Spring配置文件中<property>元素所指定的属性名和Bean实现类的Setter方法满足Sun JavaBean的属性命名规范,即xxx的属性对应setXxx()的方法。一般情况下,java的属性变量名都以小写字母开头,但考虑到一些特殊意义的英文缩略词,java bean也允许一些大写字母开头的变量名。但必须满足特点的条件:
变量的前两个字母要么全部大写,要么全部小写
但以编程经验来说:最好属性名全部使用小写字母,方便编程。
对于使用属性注入方法来说,只能人为在配置文件中提供保证,而无法在语法级别提供保证。那么这时我们便要介绍如下这种注入方式:构造函数注入,通过这种方法便可以很好的满足要求。
二.构造函数注入
构造函数注入是除属性注入之外的另一种常用的注入方式,它保证一些必要的属性在Bean实例化时就得到了设置,并在实例化后就可以使用。
使用构造函数注入的前提是:bean必须提供带参的构造函数。
对于构造函数注入,配置文件可以有以下几种方式:
按类型匹配入参
按索引匹配入参
联合使用类型和索引匹配入参
通过自身类型反射匹配入参
1.按照类型匹配入参方式:
先来看一下bean 代码:
public class Car{
private String brand;
private double price;
public Car(String brand, double price) {
this.brand = brand;
this.price = price;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
我们为bean编写配置文件
<bean id="Car" class="cn.lovepi.chapter02.reflect.Car">
<constructor-arg type="String">
<value>红旗CA72</value>
</constructor-arg>
<constructor-arg type="double">
<value>26666</value>
</constructor-arg>
</bean>
Spring的配置文件采用和元素标签顺序无关的配置策略。这种策略可以在一定程度上保证配置信息的确定性。
那么当bean中的构造函数的多个参数类型一样时,按照类型匹配入参的这种方式便会产生混淆,那么我们便来看一看另外一种方式:按照索引匹配入参。
2.按照索引匹配入参方法:
先来编写对应bean的代码:
public class Car{
private String brand;
private String corp;
private double price;
public Car(String brand, String corp, double price) {
this.brand = brand;
this.corp = corp;
this.price = price;
}
}
可以看到,在这个bean中的构造函数中存在两个String类型的参数,那么我们便使用索引来对其中的参数进行注入。
<bean id="Car" class="cn.lovepi.chapter02.reflect.Car">
<constructor-arg index="0" value="红旗CA72"/>
<constructor-arg index="1" value="中国一汽"/>
<constructor-arg index="2" value="2666"/>
</bean>
注意:
在属性注入时,Spring按java bean 的规范确定配置属性和对应的setter方法,并使用java 反射机制调用属性的setter方法完成属性注入。但java反射机制并不会记住构造函数的入参名。因此我们不能通过指定构造函数的入参名称来进行构造函数的配置,所以我们只能通过入参的类型及其索引来间接的完成构造函数的属性注入。
3.联合使用类型和索引匹配入参
在某些复杂的配置文件当中,需要使用type和index同时出马才能完成构造函数的参数注入。那么接下里我们看一下下面的这个例子:
public class Car{
private String brand;
private String corp;
private double price;
private int maxSpeed;
public Car(String brand, String corp, double price) {
this.brand = brand;
this.corp = corp;
this.price = price;
}
public Car(String brand, String corp, int maxSpeed) {
this.brand = brand;
this.corp = corp;
this.maxSpeed = maxSpeed;
}
}
在这个类中,有两个重载的构造函数,他们都有三个入参,在这种情况下使用type和index的方法都不能完成要求,这时候就需要联合他们两个属性一起使用了。
接下来我们来看一看相应的配置文件:
<bean id="Car" class="cn.lovepi.chapter02.reflect.Car">
<constructor-arg index="0" type="String">
<value>红旗CA72</value>
</constructor-arg>
<constructor-arg index="1" type="String">
<value>中国一汽</value>
</constructor-arg>
<constructor-arg index="2" type="int">
<value>200</value>
</constructor-arg>
</bean>
可以看到其实重点在于第三个入参的类型,所以我们在配置文件中对其指定了索引和类型,这样便使得Spring可以知道对那个构造函数进行参数注入了。
注意:
假如我们的配置文件中存在歧义问题,Spring容器是可以正常启动的。并不会报错,他将随机采用一个匹配的构造函数实例化bean。而随机选择的构造函数可能并不是用户所需要的,所以我们在编程时必须小心避免出现这种歧义情况的出现。
4.通过自身类型反射匹配入参
如果bean构造函数入参的类型是可辨别的,由于java反射机制可以获取构造函数入参的类型,即使构造函数的注入不提供类型和索引的信息,Spring依旧可以完成构造函数信息的注入。
下面的示例代码当中的Boss类的构造函数的入参类型就是可以辨别的:
public class Boss {
private String name;
private Car car;
private Office office;
public Boss(String name, Car car, Office office) {
this.name = name;
this.car = car;
this.office = office;
}
}
在其配置文件当中便可以直接配置入参值。
<bean id="Boss" class="cn.lovepi.chapter03.scope.Boss">
<constructor-arg>
<value>wang</value>
</constructor-arg>
<constructor-arg>
<ref bean="car"/>
</constructor-arg>
<constructor-arg>
<ref bean="office"/>
</constructor-arg>
</bean>
以上的几种方法都可以实现构造函数参数的注入,但是为了避免问题的发生,建议还是使用显示的index和type来配置构造函数的入参信息。
三.工厂方法注入方法
工厂方法是应用中被经常使用的设计模式,也是控制反转和单实例设计思想的主要实现方法。
工厂类负责创建一个或多个工厂类实例,工厂类方法一般以接口或抽象类变量的形式返回目标类实例。
工厂类对外屏蔽了目标类的实例化步骤,调用者甚至根本不用指定具体的目标类是什么。
由于Spring容器以框架的方法提供工厂方法的功能,并以透明的方式开放给开发者。因此很少需要手工编写工程方法。但在一些遗留系统或第三方类库中还是会碰到工厂方法,此时便可以使用Spring工厂注入的方法来进行Spring的注入。
Spring工厂注入的方法可以分为静态和非静态两种:
1.非静态工厂方式
有些工厂方法是非静态的,则必须实例化工厂类后才能调用工厂方法。
下面来看一个代码示例:
public class CarFactory{
public Car createHongQiCar(){
Car car=new Car();
car.setBrand("红旗CA72");
return car;
}
}
配置文件编写:
<bean id="carFactory" class="cn.lovepi.chapter02.reflect.CarFactory"/>
<bean id="car" factory-bean="carFactory"
factory-method="createHongQiCar">
</bean>
由于carFactory的工厂方法不是静态的,所以首先需要定义一个工厂类的bean,然后通过factory-bean这个属性来引用工厂bean实例。在通过属性factory-method来指定对应的工厂方法。
2.静态工厂方法
很多工厂类方法都是静态的,这意味在无须创建工厂类实例的情况下就可以调用工厂类方法。
因此静态工厂方法比非静态工厂方法的调用更加方便。
那么我们来看静态工厂方法的bean代码:
public class CarFactory{
public static Car createCar(){
Car car=new Car();
car.setBrand("红旗CA72");
return car;
}
}
则其配置文件为:
<bean id="car" class="cn.lovepi.chapter02.reflect.Car” factory-method="createCar"></bean>
总结:
Spring提供了三种可供选择的注入方式,在实际应用中,我们究竟应该选择哪种注入方式,并没有统一的标准,如下是一些可以参考的理由:
构造函数注入理由:
构造函数保证重要属性预先设置
无需提供每个属性Setter方法,减少类的方法个数
可更好的封装类变量,避免外部错误调用
属性注入理由:
属性过多时,构造函数变的臃肿可怕
构造函数注入灵活性不强,有时需要为属性注入null值
多个构造函数时,配置上产生歧义,复杂度升高
构造函数不利于类的继承和扩展
构造函数注入会引起循环依赖的问题
其实,Spring为我们注入参数提供了这些多方法那么他们必然有他们在某一问题上的优势性,那么我们只需按照我们具体的使用需求选择适合我们的方法来使用就好了,但在这里不推荐的方法就是工厂方法注入。
---------------------
作者:wangxin1248
来源:CSDN
原文:https://blog.csdn.net/icarus_wang/article/details/51588284
版权声明:本文为博主原创文章,转载请附上博文链接!
Spring学习(十八)Bean 的三种依赖注入方式介绍的更多相关文章
- 深入浅出spring IOC中三种依赖注入方式
深入浅出spring IOC中三种依赖注入方式 spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和 ...
- Spring学习之实例化bean的三种方式
实例化bean的三种方式 构造器实例化bean Person.java public class Person { private String name; private Integer age; ...
- 【SSH系列】深入浅出spring IOC中三种依赖注入方式
spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和依赖查找,依赖什么?为什么需要依赖?注入什么?控 ...
- spring IOC中三种依赖注入方式
Spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则,用来消减计算机程序之间的耦合问题,控制反转一般分为两种类型,依赖注入和依赖查找,依赖什么?为什么需要依赖?注入 ...
- [心得笔记]spring常用的三种依赖注入方式
一.目前使用最广泛的 @Autowired:自动装配 基于@Autowired的自动装配,默认是根据类型注入,可以用于构造器.接口.方法注入,使用方式如下: @Autowired 构造方法.方法.接口 ...
- 转:深入浅出spring IOC中四种依赖注入方式
转:https://blog.csdn.net/u010800201/article/details/72674420 深入浅出spring IOC中四种依赖注入方式 PS:前三种是我转载的,第四种是 ...
- spring四种依赖注入方式(转)
spring四种依赖注入方式!! 平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提 ...
- spring几种依赖注入方式以及ref-local/bean,factory-bean,factory-method区别联系
平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程 ...
- ASP.NET Core应用的7种依赖注入方式
ASP.NET Core框架中的很多核心对象都是通过依赖注入方式提供的,如用来对应用进行初始化的Startup对象.中间件对象,以及ASP.NET Core MVC应用中的Controller对象和V ...
随机推荐
- 基于CentOS6.8版本配置真实域名的方法
前言:审核了15天的时间终于审核下来了,但是结果发现配置域名掉坑了,记录一下 (一)首先配置域名三步走 1.先到域名商网站解析你你的域名(我的是百度云) 2.接着修改linux的host指向 例如: ...
- Win10升级.NET Framework 3.5或2.0遇到错误0x800f081f怎么办
为了让win10系统更好地运行游戏,很多玩家都会在电脑中安装.NET Framework 3.5或.NET Framework 2.0.不过,部分用户在更新升级.NET Framework 3.5和2 ...
- 深入理解Python异步编程(上)
本文代码整理自:深入理解Python异步编程(上) 参考:A Web Crawler With asyncio Coroutines 一.同步阻塞方式 import socket def blocki ...
- 搭建VirtualBox虚拟机集群
===============================VirtualBox常用网络===============================NetworkAddress Translati ...
- 【由浅入深理解java集合】(五)——集合 Map
前面已经介绍完了Collection接口下的集合实现类,今天我们来介绍Map接口下的两个重要的集合实现类HashMap,TreeMap.关于Map的一些通用介绍,可以参考第一篇文章.由于Map与Lis ...
- 2017CCPC秦皇岛 A题Balloon Robot&&ZOJ3981【模拟】
题意: 一个机器人在长为M的圆形轨道上送气球,当机器人到达M号点的时候下一站会回到1号点,且全程不会停止运动.现在在长为M的轨道上有N个队伍,队伍会在某个时间做需要一个气球,机器人需要送过去.一共有P ...
- react路由的安装及格式和使用方法
react路由的安装: 在要创建项目的目录命令窗里输入: cnpm install -g create-react-app create-react-app 项目名 在创建好的项目目录命令窗里输入: ...
- Charles手机抓包设置&无法打开火狐网页设置
1. Charles抓取手机上的网络包,需要安装证书(Charles的和手机的) 操作方法: https://blog.csdn.net/lea__dongyang/article/details/7 ...
- LOJ #6374「SDWC2018 Day1」网格
模拟赛考过的题 当时太菜了现在也一样只拿到了$ 30$分 回来填个坑 LOJ #6374 题意 你要从$ (0,0)$走到$ (T_x,T_y)$,每次移动的坐标增量满足$ 0 \leq \Delta ...
- Loadrunner 如何在其他浏览器进行录制(一)
背景: 由于lr只支持低版本的IE浏览器,当我们想使用高版本或其他浏览器进行录制时,这时,我们需要用到浏览器的代理功能. 传统的访问模式如下: 使用代理后的访问方式: 下面来总结一下具体的步骤: 1. ...