一、依赖注入
一、依赖注入
1.依赖注入的理解
(1)A对象需要调用B对象方法,称A对象依赖B对象;
(2)依赖注入通常有两种,即设值注入和构造注入;
2.设值注入
(1)Bean与Bean之间的依赖关系由Spring管理,Spring采用setter方法为目标Bean注入所以来的Bean这种方式被称为依赖注入;
(2)示例:
Person接口:
public interface Person { //定义一个用斧头的方法 public void useAxe(); }
Axe接口:
public interface Axe { //定义一个chop()方法 public String chop(); }
Person实现类Chinese:
public class Chinese implements Person{ private Axe axe; //设置注入需要的setter方法 public void setAxe(Axe axe){ this.axe = axe; } //实现Person接口的useAxe()方法 @Override public void useAxe() { // TODO Auto-generated method stub //调用axe的chop()方法 //表明Person对象依赖于Axe对象 System.out.println(axe.chop()); } }
Axe实现类stoneAxe:
public class StoneAxe implements Axe{ @Override public String chop() { // TODO Auto-generated method stub return "石斧砍柴好慢"; } }
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <!-- Spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 --> <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.0.xsd" > <!-- 配置chinese实例,其实现类是test1.Chinese --> <bean id="chinese" class="test1.Chinese"> <!-- 驱动调用chinese的setAxe()方法,将容器中的stoneAxe对象作为参数传入 --> <property name="axe" ref="stoneAxe"/> </bean> <!-- 配置stoneAxe实例,其实现类是test1.StoneAxe --> <bean id="stoneAxe" class="test1.StoneAxe"/> </beans>
主程序:
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { //创建Spring容器 ApplicationContext ctx = new ClassPathXmlApplicationContext("test1.xml"); //获取chinese实例 Person p = ctx.getBean("chinese",Chinese.class); //调用useAxe()方法 p.useAxe(); } }
3.构造注入
(1)在构造实例时,已经为其完成了依赖关系的初始化,这种利用构造器来设置依赖关系的方式被称为构造注入;
(2)示例:
Person接口:
public interface Person { //定义一个使用斧头的方法 public void useAxe(); }
Person的实现类Chinese:
public class Chinese implements Person{ private Axe axe; //构造注入所需的构造方法 public Chinese(Axe axe){ this.axe = axe; } @Override public void useAxe() { // TODO Auto-generated method stub //调用axe的chop()方法 //说明Person对象依赖于Axe对象 System.out.println(axe.chop()); } }
Axe接口:
public interface Axe { //定义一个chop()方法 public String chop(); }
Axe接口的实现类StoneAxe:
public class StoneAxe implements Axe{ @Override public String chop() { // TODO Auto-generated method stub return "石斧砍柴好慢"; } }
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <!-- Spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 --> <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.0.xsd" > <!-- 配置名为chinese的实例,其实现类是test2.Chinese --> <bean id="chinese" class="test2.Chinese"> <!-- 构造注入axe对象 --> <constructor-arg ref="stoneAxe"/> </bean> <!-- 配置名为stoneAxe的实例 --> <bean id="stoneAxe" class="test2.StoneAxe"/> </beans>
主程序:
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) throws Exception{ //创建Spring容器 ApplicationContext ctx = new ClassPathXmlApplicationContext("test2.xml"); //获取chinese实例 Person p = ctx.getBean("chinese",Chinese.class); //调用chinese对象的useAxe()方法 p.useAxe(); } }
4.两种注入方式的对比
(1)设值注入的优势:
1)通过setter方法设定依赖关系更自然、直观;
2)对于复杂的依赖关系,如果使用构造注入,会导致构造器臃肿难以阅读;
(2)构造注入的优势:
1)可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入;
2)对于依赖关系无须变化的Bean,构造注入无须担心后续代码对依赖关系的破坏;
3)依赖关系只能在构造器中设定,则只有组件的创建者才能改变组件的依赖关系,对组件的调用者而言,组件内部的依赖关系完全透明,更符合高内聚的原则。