Spring之依赖注入

     一、高度耦合对象引用 

    
实际的项目开发不可能全部在一个类中完成,都是由多个类组成,这些类相互之间进行写作完成特定的业务逻辑。通常,每个对象负责管理与自己相互协作的对象的引用,这将会导致对象之间的高度耦合。

   例如:

 1 package com.springinaction.knights;
 2 public class DamselRescuingKnight implements Knight {
 3     private RescueDamselQuest quest;
 4     
 5     public DamselRescuingKnight() {
 6         quest = new RescueDamselQuest();
 7     }
 8     
 9     public void embarkOnQuest() throws QuestException{
10         quest.embark();
11     }
12 }

    DamselRescuingKnight只能执行RescueDamselQuest的探险任务,而且DamselRescuingKnight与RescueDamselQuest形成了紧耦合的关系,极大的限制了这个骑士执行探险的能力。

二、构造器依赖注入
另一种方式,通过依赖注入(DI),对象的依赖关系将由负责协调系统中各个对象的第三方组件在创建对象时设定。对象无需自行创建或管理它们的依赖关系,依赖关系被自动注入到需要它们的对象中去。为了展示这一点,看如下代码示例。

 1 package com.springinaction.knights;
 2 public class BraveKnight implements Knight {
 3     private Quest quest;
 4     
 5     public BraveKnight(Quest quest) {
 6         this.quest = quest;
 7     }
 8     
 9     public void embarkOnQuest() throws QuestException {
10         quest.embark();
11     }
12 }

通过这段示例,正如看到的那样,不同于之前的DamselRescuingKnight,BraveKnight没有自行创建探险任务,而是在构造时把探险任务作为构造器参数传入。这是依赖注入的方式之一,即构造器注入。

三、xml配置文件装配Bean的方式
现在BraveKnight类可以接受你传递它的任何一种Quest的实现,但如何把特定的Quest实现传递给它呢?
创建应用组件之间协作的行为通常称为装配。Spring有多种装配Bean的方式,采用XML配置通常是最常见的装配方式,一个简单的Spring配置文件:knights.xml,该配置文件让BraveKnight接受了一个SlayDragonQuest探险任务。

 1 <beans default-autowire="byName"
 2     xmlns="http://www.springframework.org/schema/beans"
 3         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4         xsi:schemaLocation="http://www.springframework.org/schema/beans
 5         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 6         <bean id="knight" class="com.springinaction.knights.BraveKnight">
 7             <constructor-arg ref="quest" />
 8         </bean>
 9         
10         <bean id="quest" class="com.springinaction.knights.SlayDragonQuest" />
11 </beans>

xml文件中声明了BraveKnight和Quest的关系。

四、观察它如何工作
Spring通过应用上下文(Application Context)装载Bean的定义并把他们组装起来。Spring应用上下文全权负责对象的创建和组装。Spring自带了几种应用上下文的实现,他们之间主要的区别仅仅是如何加载它们的配置。
因为knights.xml中的Bean是在XML文件中声明的,所以选择ClassPathX-mlApplicationContext作为应用上下文是相对比较合适的。该类加载位于应用系统classpatch下的一个或多个XML文件。下面的代码示例中的main()方法调用了
ClassPathXmlApplicationContext加载knights.xml,并获得Knight对象的引用。

 1 package com.springinaction.knights;
 2 import org.springframework.context.ApplicationContext;
 3 import org.springframework.context.support.ClassPathXmlApplicationContext;
 4 
 5 public class KnightMain {
 6     public static void main(String[] args) {
 7         ApplicationContext context = new ClassPathXmlApplicationContext("knights.xml");
 8         Knight knight = (Knight) context.getBean("knight");
 9         knight.embarkOnQuest();
10     }
11 }

这里的main()方法创建了一个Spring应用上下文,该应用上下文加载了knights.xml文件。然后调用了该应用上下文获取一个ID为knight的Bean,得到了Knight对象的应用。

 

 

 

相关文章