依赖注入:让调用类对某一接口实现类的依赖关系由第三方注入,以移除调用类对某一接口实现类的依赖。
接下来将详细的向大家介绍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 的三种依赖注入方式介绍的更多相关文章

  1. 深入浅出spring IOC中三种依赖注入方式

    深入浅出spring IOC中三种依赖注入方式 spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和 ...

  2. Spring学习之实例化bean的三种方式

    实例化bean的三种方式 构造器实例化bean Person.java public class Person { private String name; private Integer age; ...

  3. 【SSH系列】深入浅出spring IOC中三种依赖注入方式

    spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则来消减计算机程序的耦合问题,控制反转一般分为两种类型,依赖注入和依赖查找,依赖什么?为什么需要依赖?注入什么?控 ...

  4. spring IOC中三种依赖注入方式

    Spring的核心思想是IOC和AOP,IOC-控制反转,是一个重要的面向对象编程的法则,用来消减计算机程序之间的耦合问题,控制反转一般分为两种类型,依赖注入和依赖查找,依赖什么?为什么需要依赖?注入 ...

  5. [心得笔记]spring常用的三种依赖注入方式

    一.目前使用最广泛的 @Autowired:自动装配 基于@Autowired的自动装配,默认是根据类型注入,可以用于构造器.接口.方法注入,使用方式如下: @Autowired 构造方法.方法.接口 ...

  6. 转:深入浅出spring IOC中四种依赖注入方式

    转:https://blog.csdn.net/u010800201/article/details/72674420 深入浅出spring IOC中四种依赖注入方式 PS:前三种是我转载的,第四种是 ...

  7. spring四种依赖注入方式(转)

    spring四种依赖注入方式!! 平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提 ...

  8. spring几种依赖注入方式以及ref-local/bean,factory-bean,factory-method区别联系

    平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程 ...

  9. ASP.NET Core应用的7种依赖注入方式

    ASP.NET Core框架中的很多核心对象都是通过依赖注入方式提供的,如用来对应用进行初始化的Startup对象.中间件对象,以及ASP.NET Core MVC应用中的Controller对象和V ...

随机推荐

  1. Java实现OPC通信

    1.PLC和OPC 使用的PLC:西门子的S7 300,具体型号如下图 使用的OPC server软件: 模拟仿真用的 MatrikonOPCSimulation(50M),百度网盘,密码: mcur ...

  2. 2018牛客网暑期ACM多校训练营(第三场)C Shuffle Cards(可持久化平衡树/splay)

    题意 牌面初始是1到n,进行m次洗牌,每次抽取一段放到最前面.求最后的序列. 分析 神操作!!!比赛时很绝望,splay技能尚未点亮,不知道怎么用. 殊不知,C++库里有rope神器,即块状链表. 基 ...

  3. 简述react与vue的区别

    React 和Vue是现在主流的两个框架(相对来说angular用的已经少了) 两者的区别体现在以下方面 相同点: 1.react和vue都支持服务端渲染 2.都有虚拟DOM,组件化开发,通过prop ...

  4. vmware+centos

    centos 7 在安装的时候使用 net.ifname=0 biosdevname=0 使网卡名和以前一样 /boot 引导系统启动,内核 /swap 交换分区,临时作为内存使用防止内存不够使用导致 ...

  5. 面向对象(Object Orientation Programming)

    Three characteristic of object orientation: Encapsulation: capturing data and keeping it safely and ...

  6. 开源ETL工具之Kettle介绍

    What 起源 Kettle是一个Java编写的ETL工具,主作者是Matt Casters,2003年就开始了这个项目,最新稳定版为7.1. 2005年12月,Kettle从2.1版本开始进入了开源 ...

  7. Tooltip导致的无法访问已释放对象

    最近C#项目中遇到了一个无法访问已释放对象问题,经过反复测试,最终发现问题出在控件Tootip上,因为tootip内部有一个定时器,如果在窗口销毁时,鼠标移动到控件上恰好产生了一个tooltip,就会 ...

  8. JS创建对象之组合使用构造函数模式和原型模式

    function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.friends = { ...

  9. Intelij IDEA 内置 sql gui

    IDEA 内置 自带 SQL GUI  最大意义 会自动识别 domain 对象与数据表的关系,也可以通过 Database 的数据表直接生成 domain 对象等等. 第一步 打开数据库视图 Vie ...

  10. Linux LVM 逻辑分区

    LVM是 Logical Volume Manager(逻辑卷管理)的简写,它是Linux环境下对磁盘分区进行管理的一种机制,它由Heinz Mauelshagen在Linux 2.4内核上实现.普通 ...