4 Spring依赖注入(DI)

作者: 笑Skr人啊 | 来源:发表于2017-05-05 15:26 被阅读48次

在Spring框架中,依赖注入(DI)的设计模式是用来定义对象彼此间的依赖。它主要有两种类型:

  • Setter方法注入
  • 构造器注入

1 Setter方法注入

这是最流行最简单的DI注入方法,通过设置方法注入依赖。

  • a) 接口类: IOutputGenerator.java
package com.gp6.service;

public interface IOutputGenerator {
    public void generateOutput();
}

  • b) 实现类
package com.gp6.service.impl;

import com.gp6.service.IOutputGenerator;

public class CsvOutputGenerator implements IOutputGenerator{
    public void generateOutput(){
        System.out.println("Csv Output Generator");
    }
}

  • c) Helper类

一个辅助类,之后使用Spring 来注入 IOutputGenerator。

package com.gp6.help;

import com.gp6.service.IOutputGenerator;

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

}

  • d) Spring配置

配置Bean在Spring配置文件,并引用Bean “CsvOutputGenerator” 到 “OutputHelper”,通过property 和 ref 标签。
在这种情况下,Spring将通过setter方法注入Bean “CsvOutputGenerator” 到“OutputHelper”类,“setOutputGenerator(IOutputGenerator outputGenerator)”.

<?xml version="1.0" encoding="UTF-8"?>

<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.gp6.help.OutputHelper">
        <property name="outputGenerator" ref="CsvOutputGenerator" />
    </bean>
    
    <bean id="CsvOutputGenerator" class="com.gp6.service.impl.CsvOutputGenerator" />
        
</beans>
  • e) 执行结果

载入一切东西,并运行它。

package com.gp6.test;

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

import com.gp6.help.OutputHelper;

public class SpringTest02 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        ApplicationContext context = 
                   new ClassPathXmlApplicationContext(new String[] {"Spring01.xml"});

        OutputHelper output = (OutputHelper)context.getBean("OutputHelper");
        output.generateOutput();
    }
}

输出结果:

This is Csv Output Generator

2 构造函数注入

此DI方法将通过构造函数注入依赖。

  • a) 接口类: IOutputGenerator.java
package com.gp6.service;

public interface IOutputGenerator {
    public void generateOutput();
}

  • b) 实现类
package com.gp6.service.impl;

public class JsonOutputGenerator {
    public void generateOutput(){
        System.out.println("Json Output Generator");
    }
}

  • c) Helper类

一个辅助类,之后使用Spring 来注入 IOutputGenerator。

package com.gp6.help;

import com.gp6.service.IOutputGenerator;

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

}

  • d) Spring配置

请参阅下面的 Spring bean 配置,Spring 将通过构造函数注入上面的 “JsonOutputGenerator” 到 “OutputHelper” 类,“public OutputHelper(IOutputGenerator outputGenerator)“.
只需通过一个构造函数注入一个 “CsvOutputGenerator” Bean 到 “OutputHelper” 对象。

<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.gp6.OutputHelper">
        <constructor-arg>
            <ref bean="JsonOutputGenerator" />
        </constructor-arg>
    </bean>
 
    <bean id="JsonOutputGenerator" class="com.gp6.service.impl.JsonOutputGenerator" />

</beans>
  • w) 执行结果

载入一切东西,并运行它。

package com.gp6.test;

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

import com.gp6.help.OutputHelper;

public class SpringTest02 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        ApplicationContext context = 
                   new ClassPathXmlApplicationContext(new String[] {"Spring01.xml"});

        OutputHelper output = (OutputHelper)context.getBean("OutputHelper");
        output.generateOutput();
    }
}

输出结果

This is Json Output Generator

  • setter方法还是构造函数注入?

Spring框架的设置有没有硬性规定,只需要使用适合你的项目需要的类型注入。然而,由于setter方法注入简单,它总是大部分使用场景的选择

  • Spring构造方法注入类型歧义

在Spring框架中,当一个类包含多个构造函数带的参数相同,它总是会造成构造函数注入参数类型歧义的问题。

Example:

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

  • a) 让我们来看看这个客户 bean 实例。它包含两个构造方法,均接受3个不同的数据类型参数。
package com.gp6.bean;

public class Customer {
    private String name;
    private String address;
    private int age;

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

  • b) 在Spring bean 的配置文件中,通过传递一个'gp6' 的名字,地址为'244',以及年龄为'24'。
<?xml version="1.0" encoding="UTF-8"?>

<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.gp6.bean.Customer ">

        <constructor-arg>
            <value>gp6</value>
        </constructor-arg>
        
        <constructor-arg>
            <value>244</value>
        </constructor-arg>
        
        <constructor-arg>
            <value>24</value>
        </constructor-arg>
        </bean>
        
</beans>
  • c) 运行
package com.gp6.test;

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

import com.gp6.bean.Customer;
import com.gp6.bean.JavaConfigImport01;
import com.gp6.bean.JavaConfigImport02;
import com.gp6.help.JavaConfigImportTestAll;

public class SpringTest06 {

     public static void main( String[] args ) {
        ApplicationContext context = 
          new ClassPathXmlApplicationContext(new String[] {"Spring02.xml"});

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


  • d) 运行结果:
    name : gp6
    address : 24
    age : 244

其结果不是我们所期望的,第一个构造器执行,而是第二构造函数不运行。在Spring参数类型'244' 能够转换成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)
  • e) 解决

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

<?xml version="1.0" encoding="UTF-8"?>

<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.gp6.bean.Customer">

        <constructor-arg type="java.lang.String">
            <value>gp6</value>
        </constructor-arg>
        
        <constructor-arg type="java.lang.String">
            <value>244</value>
        </constructor-arg>
        
        <constructor-arg type="int">
            <value>24</value>
        </constructor-arg>
        </bean>
        
</beans>
  • f) 运行结果:
    name : gp6
    address : 244
    age : 24

相关文章

  • spring

    spring4介绍 spring配置详解 IOC(控制反转) 与 DI(依赖注入)重点 依赖注入各种类型const...

  • 初识Spring架构

    对Spring的了解 依赖注入DI(Dependency injection) DI分为依赖和注入 那怎么将对象注...

  • 4 Spring依赖注入(DI)

    在Spring框架中,依赖注入(DI)的设计模式是用来定义对象彼此间的依赖。它主要有两种类型: Setter方法注...

  • @Autowired 和 @Resource 注解

    Spring 利用依赖注入(DI), 为 Spring IoC 容器赋值。@Autowired 是 Spring ...

  • Spring IOC容器

    由于Spring是采用依赖注入(DI)的方式来实现IOC,所以本文将IOC和依赖注入(DI)等同看待,主要讨论依赖...

  • Spring 的属性注入

    Spring 的属性注入 Spring 的属性注入,我们可以理解成之前说过的 DI (依赖注入)。 注入方式 对于...

  • spring 那点事

    Spring核心功能 DI(IOC) 何谓DI(IOC) DI(依赖注入)是spring的核心功能之一。Depen...

  • spring之控制反转和依赖注入

    Spring学习(三)IOC控制反转与DI依赖注入

  • 依赖注入

    依赖注入(DI) Spring 最认同的技术是控制反转的依赖注入(DI)模式。控制反转(IoC)是一个通用的概念,...

  • “王大锤の非诚勿扰” —— Spring IoC / DI 思想

    本文参考地址: 《spring Ioc/DI的理解》 《关于Spring IOC (DI-依赖注入)你需要知道的...

网友评论

    本文标题:4 Spring依赖注入(DI)

    本文链接:https://www.haomeiwen.com/subject/myqstxtx.html