在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
网友评论