Spring重温(三)--Spring依赖注入(DI)

前言:在Spring框架中,DI(依赖注入)是用来定义对象彼此间的依赖,主要有set方法注入和构造器注入两种方式。另外,当一个类包含多个构造函数带的参数相同,它老是会形成构造函数注入参数类型歧义的问题,我会在第3点进行介绍并给出解决方案。java

1.setter方法注入:spring

package com.yiibai.output;

import com.yiibai.output.IOutputGenerator;

public class OutputHelper
{
    IOutputGenerator outputGenerator;
    
    public void setOutputGenerator(IOutputGenerator outputGenerator){
        this.outputGenerator = outputGenerator;
    }
    
}

一个 bean 配置文件用来声明bean 和经过 setter 设置注入(property标签)的依赖。框架

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="OutputHelper" class="com.yiibai.output.OutputHelper">
        <property name="outputGenerator">
            <ref bean="CsvOutputGenerator" />
        </property>
    </bean>
    
<bean id="CsvOutputGenerator" class="com.yiibai.output.impl.CsvOutputGenerator" />
</beans>

2.构造器注入:yii

例子:函数

package com.yiibai.output;

import com.yiibai.output.IOutputGenerator;

public class OutputHelper
{
    IOutputGenerator outputGenerator;
    
        OutputHelper(IOutputGenerator outputGenerator){
        this.outputGenerator = outputGenerator;
    }
}

bean 配置文件来声明bean并经过构造函数(constructor-arg标签)设置注入依赖ui

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="OutputHelper" class="com.yiibai.output.OutputHelper">
        <constructor-arg>
            <bean class="com.yiibai.output.impl.CsvOutputGenerator" />
        </constructor-arg>
    </bean>
    
<bean id="CsvOutputGenerator" class="com.yiibai.output.impl.CsvOutputGenerator" />
        
</beans>

 3.当一个类包含多个构造函数带的参数相同,它老是会形成构造函数注入参数类型歧义的问题。this

 让咱们来看看这个客户 bean 实例。它包含两个构造方法,均接受3个不一样的数据类型参数:spa

package com.yiibai.common;

public class Customer 
{
    private String name;
    private String address;
    private int age;
    
    public Customer(String name, String address, int age) {
        this.name = name;
        this.address = address;
        this.age = age;
    }
    
    public Customer(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    //getter and setter methods
    public String toString(){
        return " name : " +name + "\n address : "
               + address + "\n age : " + age;
    }

}

在Spring bean 的配置文件中,咱们传递一个“yiibai' 的名字,地址为'188',以及年龄为'28'。code

<!--Spring-Customer.xml-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="CustomerBean" class="com.yiibai.common.Customer">

        <constructor-arg>
            <value>yiibai</value>
        </constructor-arg>
        
        <constructor-arg>
            <value>188</value>
        </constructor-arg>
        
        <constructor-arg>
            <value>28</value>
        </constructor-arg>
        </bean>

</beans>

运行它,你指望的结果是什么?xml

package com.yiibai.common;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App 
{
    public static void main( String[] args )
    {
        ApplicationContext context = 
          new ClassPathXmlApplicationContext(new String[] {"Spring-Customer.xml"});

        Customer cust = (Customer)context.getBean("CustomerBean");
        System.out.println(cust);
    }
}

输出结果:

name : yiibai
 address : 28
 age : 188

其结果不是咱们所指望的,第一个构造器不执行,而是第二构造函数运行。在Spring参数类型'188' 可以转换成int,因此Spring只是转换它,并采用第二个构造来执行,即便你认为它应该是一个字符串。

另外,若是Spring不能解决使用哪一个构造函数,它会提示如下错误信息
constructor arguments specified but no matching constructor 
found in bean 'CustomerBean' (hint: specify index and/or 
type arguments for simple parameters to avoid type ambiguities

为了解决这个问题,应该为构造函数指定的确切数据类型,经过像这样类型的属性:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="CustomerBean" class="com.yiibai.common.Customer">
    
        <constructor-arg type="java.lang.String">
            <value>yiibai</value>
        </constructor-arg>
        
        <constructor-arg type="java.lang.String">
            <value>188</value>
        </constructor-arg>
        
        <constructor-arg type="int">
            <value>28</value>
        </constructor-arg>
        
    </bean>

</beans>

再次运行它,如今获得你所指望的:

name : yiibai
 address : 188
 age

 

 

总结:在依赖注入中,主要有seter方法注入和构造函数注入两种方式,其中setter方法注入是在xml配置文件中经过property设置依赖,而构造器经过constructor-arg设置依赖;

         显式声明每一个构造函数参数的数据类型,能够避免上述构造注入型歧义的问题。

相关文章
相关标签/搜索