Spring依赖注入的三种方式

来源:互联网 发布:日本留学费用 知乎 编辑:程序博客网 时间:2024/05/14 05:05

Spring支持两种依赖注入方式,分别是属性注入和构造函数注入。除此之外,Spring还支持工厂方法注入。

1.属性注入

实体类Car,有三个属性

public class Car {    private int maxSpeed;    private String brand;    private double price;    public int getMaxSpeed() {        return maxSpeed;    }    public void setMaxSpeed(int maxSpeed) {        this.maxSpeed = maxSpeed;    }    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.xml

<bean id = "car" class = "com.smart.ditype.Car">        <property name="maxSpeed"><value>200</value></property>        <property name="brand"><value>宝马</value></property>        <property name ="price"><value>20000.00</value></property>    </bean>

上述代码配置了一个Bean,并为Bean的三个属性提供了属性值。每一个属性对应一个标签,name为属性名,在Bean实现类中要拥有与其对应的Setter方法。
注意:Spring只会检查Bean中是否含有Setter方法,至于Bean中是否有对应的属性成员则不做要求。

2.构造函数注入
构造函数注入是除属性注入外的另一种常用注入方式,保证一些必要的属性在Bean实例化时就得到设置,确保Bean在实例化后就可以使用。

(1)按类型匹配入参
Bean必须提供带参的构造函数

public Car(String brand,double price){    this.brand = brand;    this.price = price;…
<bean id = "car1" class="com.smart.ditype.Car">        <constructor-arg type = "java.lang.String">            <value>宝马</value>        </constructor-arg>        <constructor-arg type = "double">            <value>20000</value>        </constructor-arg></bean>

在的元素中有type属性,为Spring提供了判断配置项和构造函数入参对应关系的“信息”。
注意! 在仅有一个构造函数的情况下,的声明顺序可以用于构造函数的入参顺序。但是,Spring的配置文件采用和元素标签顺序无关的策略,这种顺序策略在一定程度上保证配置信息的准确性。

(2)按索引匹配入参

爪洼通过入参的类型和顺序区分不同的重载方法。对于刚刚的配置,有一个String属性和一个double属性,但如果有两个String属性,因为brand和crop的属性都是String,所以使用无法确定type指的是哪一个,就需要用到索引匹配入参。

public Car(String brand,String crop,double price){        this.brand = brand;        this.crop = crop;        this.price = price;    }
<bean id = "car2" class="com.smart.ditype.Car">        <constructor-arg index = "0" value = "宝马">        <constructor-arg index = "1" value = "SDAU">        <constructor-arg index = "2" value = "20000"></bean>

构造函数的第一个参数索引为0,第二个是1,以此类推。

(3)联合使用类型和索引匹配

public Car(String brand,String crop,double price){        this.brand = brand;        this.crop = crop;        this.price = price;    }public Car(String brand,String crop,int maxSpeed){        this.brand = brand;        this.crop = crop;        this.maxSpeed = maxSpeed;    }

这里Car有两个构造函数,都有两个入参,需要联合使用的type和index才能解决问题。

<bean id = "car3" class="com.smart.ditype.Car">        <constructor-arg index = "0" type = "java.lang.String">        <value>宝马</value>        </constructor-arg>        <constructor-arg index = "1" type = "java.lang.String">        <value>SDAU</value>        </constructor-arg>        <constructor-arg index = "2" type = "int">        <value>200</value>        </constructor-arg></bean>

这个Bean的配置对应(String brand,String crop,int maxSpeed)构造函数。
如果只通过index进行配置,Spring无法确定第三个入参的配置项是int的maxSpeed还是double的price。因此需要明确制定第三个入参的类型就可以消除歧义。所以第一个和第二个中的type可以去掉。

(4)通过自身类型反射匹配入参
(5)循环依赖
这俩我也不会,暂时没用到过。用到了再学。。233

3.工厂方法注入

工厂方法在大二学过,是非常常用的设计模式,也是控制反转和单例模式的主要实现方法。SpringIoc容器以框架的方式提供工厂方法的功能。

(1)非静态工厂
有些工厂方法是非静态的,必须实例化工厂类后才能调用工厂方法。

public class CarFactory {    public Car createBMW(){        Car car = new Car();        car.setBrand("宝马320");        return car;    }}

工厂类负责创建目标类的实例,对外屏蔽实例化的步骤。

<bean id ="carFactory" class = "com.smart.ditype.CarFactory"/><bean id = "car4" factory-bean="carFactory"                  factory-method="createBMW"/>

因为不是静态的,所以定义一个工厂类的Bean,再用过factory-bean引用工厂类实例,最后通过factory-method指定对应的工厂类方法。

(2)静态工厂方法

无须在创建工厂实例的情况下就可以调用工厂类方法,因此更容易使用。只需将创建方法改成静态。

public class CarFactory {    public static Car createBMW(){        Car car = new Car();        car.setBrand("宝马320");        return car;    }}
<bean id = "car5" class = "com.smart.ditype.CarFactory" factory-method="createBMW"

对于三种注入方式,选择问题根据实际情况,无统一标准。
具体考量参照spring api。