• Home
  • About
    • wanziの遇笺 photo

      wanziの遇笺

      一点随笔,一丝感悟,一些记录,一种成长。

    • Learn More
    • Instagram
    • Github
  • Archive
  • Category
  • Tag

Spring依赖注入

25 Aug 2015

Reading time ~2 minutes

  控制反转IoC(Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。其主要实现方式有两种:

  1. 依赖查找(Dependency Lookup):容器提供回调接口和上下文环境给组件。
  2. 依赖注入(Dependency Injection):组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。后者是时下最流行的IoC类型,其又有接口注入(Interface Injection),设值注入(Setter Injection)和构造子注入(Constructor Injection)三种方式。      

一、接口注入

public class ClassA {
		private InterfaceB clzB;
		public void doSomething() {
		Ojbect obj = Class.forName(Config.BImplementation).newInstance();
		clzB = (InterfaceB)obj;
		clzB.doIt();
    }
}

  ClassA依赖于InterfaceB的实现,传统的方法是在代码中创建 InterfaceB实现类的实例,ClassA在编译期即依赖于InterfaceB的实现。

  我们预先在配置文件中设定的实现类的类名Config.BImplementation,动态加载实现类,并通过InterfaceB强制转型后为ClassA 所用,将调用者与实现者在编译期分离。

二、setter注入

先定义一个接口IOutputGenerator.java:

package com.mkyong.output;
 
public interface IOutputGenerator
{
    public void generateOutput();
}

1、CsvOutputGenerator.java

package com.mkyong.output.impl;

import com.mkyong.output.IOutputGenerator;

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

2、OutputHelper.class

package com.mkyong.output;

import com.mkyong.output.IOutputGenerator;

public class OutputHelper {
    IOutputGenerator outputGenerator;

    public void generateOutput() {
        outputGenerator.generateOutput();
    }

    //DI via setter method
    public void setOutputGenerator(IOutputGenerator outputGenerator) {
        this.outputGenerator = outputGenerator;
    }
}

3、配置Spring,在SpringBeans.xml中

把CsvOutputGenerator注入到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.mkyong.output.OutputHelper">
        <property name="outputGenerator" ref="CsvOutputGenerator" />
    </bean>
 
    <bean id="CsvOutputGenerator" class="com.mkyong.output.impl.CsvOutputGenerator" />

</beans>

4、运行,在App.java中

package com.mkyong.common;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.mkyong.output.OutputHelper;

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

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

5、结果

This is Csv Output Generator

三、构造子注入

1、CsvOutputGenerator.java

package com.mkyong.output.impl;

import com.mkyong.output.IOutputGenerator;

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

2、OutputHelper.java

package com.mkyong.output;

import com.mkyong.output.IOutputGenerator;

public class OutputHelper {
    IOutputGenerator outputGenerator;

    public void generateOutput() {
        outputGenerator.generateOutput();
    }

    //DI via constructor
    public OutputHelper(IOutputGenerator outputGenerator){
        this.outputGenerator = outputGenerator;
    }
    
}

3、Spring配置

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

</beans>

4、运行,结果

This is Json Output Generator

当有两个构造函数,且参数个数一样但参数类型不同时,则会出现构造器注入参数类型歧义的问题。下面举出另外一个例子:

Example构造子注入

1、在Customer.java中


package com.mkyong.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;
    }

}

2、Spring配置,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.mkyong.common.Customer">
	
			<constructor-arg>
				<value>mkyong</value>
			</constructor-arg>
			
			<constructor-arg>
				<value>188</value>
			</constructor-arg>
			
			<constructor-arg>
				<value>28</value>
			</constructor-arg>
	        </bean>
	
	</beans>

3、运行,在App.java中

package com.mkyong.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);
    }
}

4、结果

name : mkyong
address : 28
age : 188

  在Spring,参数188可以转换成int,所以Spring直接转换了它并用了第二个构造函数。

5、解决办法

在Spring-Customer.xml中给constructor-arg加入type。


<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.mkyong.common.Customer">
    
        <constructor-arg type="java.lang.String">
            <value>mkyong</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>



javaspring Share Tweet +1