Spring依赖注入的三种方式

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。

展开阅读全文

没有更多推荐了,返回首页