深入解读Spring Framework IoC容器(第二弹:依赖注入的方式)

依赖注入 (DI) 是指定义对象之间的依赖关系的过程。容器的工作就是创建bean并注入依赖关系。这个过程来由容器来控制bean的实例或者其依赖关系,因此它有另外一个名字叫控制反转 (IoC)。

DI主要有两种注入方式,即构造器注入和Setter注入。

构造器注入

基于构造器注入DI通过调用带参数的构造器来实现,每个参数代表着一个依赖关系。

public class ExampleBean {

    private AnotherBean beanOne;
    private YetAnotherBean beanTwo;
    private int i;

    public ExampleBean(
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
        this.beanOne = anotherBean;
        this.beanTwo = yetAnotherBean;
        this.i = i;
    }

}
<bean id="exampleBean" class="examples.ExampleBean">
    <!-- 使用嵌套的ref元素 -->
    <constructor-arg>
        <ref bean="anotherExampleBean"/>
    </constructor-arg>

    <!-- 使用直接的ref属性 -->
    <constructor-arg ref="yetAnotherBean"/>

    <constructor-arg type="int" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

bean被实例化的时候,默认按bean定义中构造器参数的定义顺序依次进行匹配。

package x.y;

public class Foo {

    public Foo(Bar bar, Baz baz) {
        // ...
    }

}
<beans>
    <bean id="foo" class="x.y.Foo">
        <constructor-arg ref="bar"/>
        <constructor-arg ref="baz"/>
    </bean>

    <bean id="bar" class="x.y.Bar"/>

    <bean id="baz" class="x.y.Baz"/>
</beans>

可以使用type属性来显式指定简单类型的构造参数类型:

package examples;

public class ExampleBean {

    private int years;

    private String ultimateAnswer;

    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }

}
<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>

也可以使用index属性来显式指定构造参数的索引:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
</bean>

还可以使用构造器参数命名来指定:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>

不过这种方式需要使用@ConstructorProperties JDK注解明确指出构造函数的参数:

package examples;

public class ExampleBean {

    // 这里属性定义省略掉了

    @ConstructorProperties({"years", "ultimateAnswer"})
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }

}

Setter注入

容器通过回调bean的setter方法来完成setter注入。

public class ExampleBean {

    private AnotherBean beanOne;
    private YetAnotherBean beanTwo;
    private int i;

    public void setBeanOne(AnotherBean beanOne) {
        this.beanOne = beanOne;
    }

    public void setBeanTwo(YetAnotherBean beanTwo) {
        this.beanTwo = beanTwo;
    }

    public void setIntegerProperty(int i) {
        this.i = i;
    }

}
<bean id="exampleBean" class="examples.ExampleBean">
    <!-- 使用嵌套的ref元素 -->
    <property name="beanOne">
        <ref bean="anotherExampleBean"/>
    </property>

    <!-- 使用直接的ref属性 -->
    <property name="beanTwo" ref="yetAnotherBean"/>
    <property name="integerProperty" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

构造器注入和Setter注入如何选择

因为可以混合使用构造器注入和setter注入,强制性依赖关系时使用构造器注入,可选的依赖关系时使用setter方法注入是比较好的经验法则。

当实现的应用组件是不可变对象时使用构造器注入,构造器注入的组件总是返回给调用者完整的初始化状态。

setter注入主要用作可选的依赖,给这些依赖分配合理的缺省值。否则,当代码使用依赖时必须进行非空检查。setter注入的一个好处是setter方法使得这个类的对象在以后的某个时候还可合理的重新配置或者重新注入。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值