1、设值注入:IoC容器使用属性的setter方法来注入被依赖的实例。
package DependencyInjection;
public interface Person {
public void useAxe(); //定义一个使用斧头的方法
}
package DependencyInjection;
public interface Axe {
public String chop(); //Axe接口里有个砍的方法
}
Person实现类
package DependencyInjection;
public class Chinese implements Person {
private Axe axe;
public void setAxe(Axe axe) { //设值注入所需的setter方法
this.axe = axe;
}
//实现Person接口useAxe方法
public void useAxe() {
System.out.println(axe.chop());
}
}
Axe实现类
package DependencyInjection;
public class StoneAxe implements Axe {
@Override
public String chop() {
// TODO Auto-generated method stub
return "石斧砍柴好慢";
}
}
package DependencyInjection;
public class SteelAxe implements Axe {
@Override
public String chop() {
// TODO Auto-generated method stub
return "钢斧砍柴真快";
}
}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd"
>
<bean id="chinese" class="DependencyInjection.Chinese">
<property name="axe" ref="stoneAxe"/>
</bean>
<bean id="stoneAxe" class="DependencyInjection.StoneAxe"/>
<bean id="steelAxe" class="DependencyInjection.SteelAxe"/>
</beans>
测试
package DependencyInjection;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BeanTest {
public static void main(String[] args) {
//创建Spring容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");
//获取chinese实例
Person p = ctx.getBean("chinese",Person.class);
p.useAxe();
}
}
结果
2、构造注入:IoC容器使用构造器来注入被依赖的实例。
Person实现类
package DependencyInjection;
public class Chinese implements Person {
private Axe axe;
public Chinese(){} //默认的构造器
public Chinese(Axe axe){ //构造注入所需的带参数的构造器
this.axe=axe;
}
//实现Person接口useAxe方法
public void useAxe() {
System.out.println(axe.chop());
}
}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd"
>
<bean id="chinese" class="DependencyInjection.Chinese">
<constructor-arg ref="steelAxe"/>
</bean>
<bean id="stoneAxe" class="DependencyInjection.StoneAxe"/>
<bean id="steelAxe" class="DependencyInjection.SteelAxe"/>
</beans>
配置<constructor-arg.../>元素时可指定一个index属性,用于指定该构造参数值将作为第几个构造参数值,例如index="0"表明该构造参数值将作为第一个构造参数。
其他以及测试代码不变,运行结果:
执行效果与设值注入相同,区别在于:创建Person实例中Axe属性的时机不同——设值注入是先通过无参数的构造器创建一个Bean实例,然后调用对应的setter方法注入依赖关系;而构造注入则直接调用有参数的构造器,当Bean实例创建完成后,已经完成了依赖关系的注入。
对比
设值注入优点:与传统的JavaBean的写法更相似,更容易理解、接受。通过setter方法设定依赖关系显得更加直观、自然。
对于复杂的依赖关系,如果采用构造注入,会导致构造器过于臃肿,难以阅读。
构造注入优点:可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入。
对于依赖关系无须变化的Bean,构造注入更有用处。因为没有setter方法,所有的依赖关系全部在构造器内设定,因此。无须担心后续 的代码对依赖关系产生破坏。
依赖关系只能在构造器中设定,则只有组件的创建者才能改变组件的依赖关系。对组建的调用者而言,组件内部的依赖关系完全透明, 更符合高内聚的原则。
建议
以设值注入为主,对于无须变化的Bean,尽量采用构造注入。