在Spring中,依赖注入(DI)模式实现了控制反转(IoC)原理。让我们通过一个例子来帮助理解依赖注入。我们先看到java版的例子,然后在此基础上加上spring的功能。就例子而言,是相当地简单。QuizMater接口暴露了popQuestion()方法。为了保持简单性,QuizMaster将只生成一个问题。

1
2
3
4
5
6
7
8
9
/**
 * QuizMaster.java
 */
package com.vaannila;
 
public interface QuizMaster {
 
    public String popQuestion();
}

StrutsQuizMaster和SpringQuizMaster类实现了QuizMaster接口,它们各自生成struts和spring相关的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * StrutsQuizMaster.java
 */
package com.vaannila;
 
public class StrutsQuizMaster implements QuizMaster {
 
    @Override
    public String popQuestion() {
        return "Are you new to Struts?";
    }
 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * SpringQuizMaster.java
 */
package com.vaannila;
 
public class SpringQuizMaster implements QuizMaster {
 
    @Override
    public String popQuestion() {
        return "Are you new to Spring?";
    }
 
}

有个QuizMasterService类向用户显示问题。QuizMasterService类关联了QuizMaster接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * QuizMasterService.java
 */
package com.vaannila;
 
public class QuizMasterService {
 
    private QuizMaster quizMaster = new SpringQuizMaster();
 
    public void askQuestion(){
        System.out.println(quizMaster.popQuestion());
    }
}

最后创建QuizProgram类来管理测验。

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * QuizProgram.java
 */
package com.vaannila;
 
public class QuizProgram {
 
    public static void main(String[] args) {
        QuizMasterService quizMasterService = new QuizMasterService();
        quizMasterService.askQuestion();
    }
 
}

看上去相当的简单,我们创建了QuizMasterService类的实例,并且调用了askQuestion()方法。当你执行program,期望的“Are you new to Spring?”将从控制台打印出来。

再看看这个例子的类图。绿色箭头表示泛化,蓝色箭头表示关联。

看的出来这种结构是紧密耦合在一起的。在QuizMasterService类中创建了QuizMaster的实例,如下所示。

1
private QuizMaster quizMaster = new SpringQuizMaster();

为了测验精通struts的人,我们需要修改QuizMasterService成这样:

1
private QuizMaster quizMaster = new StrutsQuizMaster();

因此耦合性是非常高的,这就是为什么要使用依赖注入来避免这种耦合。Spring框架提供了非常强大的容器来管理组件。容器就是基于控制反转(IoC)理念并且实现了依赖注入。这些组件仅仅需要选择一种接受资源的方式,容器会自动为组件推送资源。

下面我们替换为QuizMasterService类直接创建QuizMaster对象的方式,让容器来承担这项工作。替换了硬编码,允许容器来注入需要的依赖项。

注入依赖使用setter或构造方法注入。下面看看怎样使用setter来注入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * QuizMasterService.java
 */
package com.vaannila;
 
public class QuizMasterService {
 
    private QuizMaster quizMaster;
     
    public void setQuizMaster(QuizMaster quizMaster) {
        this.quizMaster = quizMaster;
    }
 
    public void askQuestion(){
        System.out.println(quizMaster.popQuestion());
    }
}

QuizMaster的值使用setQuizMaster()方法设置。在QuizMasterService类中,QuizMaster对象没有实例化,但仍然来访问它。通常这样做会抛出NullPointerException异常,但是容器已经实例化了这个对象,因此能很好的工作。

再作了这些改变之后,例子的类图就变成这样了。

图中多了容器,它帮助注入依赖项。

在beans.xml文件中的beans配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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.xsd">
 
    <bean id="springQuizMaster" class="com.vaannila.SpringQuizMaster"></bean>
    <bean id="strutsQuizMaster" class="com.vaannila.StrutsQuizMaster"></bean>
    <bean id="quizMasterService" class="com.vaannila.QuizMasterService">
 
        <property name="quizMaster">
            <ref local="springQuizMaster" />
        </property>
    </bean>
</beans>

定义每个bean使用bean标签。bean标签的id属性是获取这个bean的逻辑名,class属性表示了真实的bean类。property标签指向bean的属性。使用setter注入一个bean需要使用ref标签。

SpringQuizMaster的引用被注入到QuizMasterbean。当我们执行这个例子,控制台打印出“Are you new to Spring?”。

为了使QuizMaster问一个struts相关的问题,仅仅需要改变ref标签的指向。

1
2
3
4
5
6
<bean id="quizMasterService" class="com.vaannila.QuizMasterService">
    <property name="quizMaster">
 
        <ref local="strutsQuizMaster" />
    </property>
</bean>

依赖注入降低了组件之间的耦合。

要执行这个例子需要把如下的jar文件加大classpath。

antlr-runtime-3.0 commons-logging-1.0.4 org.springframework.asm-3.0.0.M3 org.springframework.beans-3.0.0.M3 org.springframework.context-3.0.0.M3 org.springframework.context.support-3.0.0.M3 org.springframework.core-3.0.0.M3 org.springframework.expression-3.0.0.M3

Spring IoC 使用详解的更多相关文章

  1. Spring IOC使用详解

    SpringIOC使用详解 一.IOC简介 IOC(Inversion of Control):控制反转,即对象创建的问题.通俗地讲就是把创建对象的代码交给了Spring的配置文件来进行的.这样做的优 ...

  2. Spring ——Spring IoC容器详解(图示)

    1.1 Spring IoC容器 从昨天的例子当中我们已经知道spring IoC容器的作用,它可以容纳我们所开发的各种Bean.并且我们可以从中获取各种发布在Spring IoC容器里的Bean,并 ...

  3. Spring IoC原理详解

    去掌握一门技术的时候,往往很多人都忽略了一点,只是一味地去写代码,原理层面的东西从来就不理会 还有就是学习的过程中,不去想为什么有了当前的写法,却有着这么一门技术可以代替它 一般来说,在写程序的时候, ...

  4. [Spring学习笔记 1 ] Spring 简介,初步知识--Ioc容器详解 基本原理。

    一.Spring Ioc容器详解(1) 20131105 1.一切都是Bean Bean可是一个字符串或者是数字,一般是一些业务组件. 粒度一般比较粗. 2.Bean的名称 xml配置文件中,id属性 ...

  5. Spring jar包详解

    Spring jar包详解 org.springframework.aop ——Spring的面向切面编程,提供AOP(面向切面编程)的实现 org.springframework.asm——spri ...

  6. Spring——jar包详解(转)

    Spring——jar包详解 org.springframework.aop ——Spring的面向切面编程,提供AOP(面向切面编程)的实现 org.springframework.asm——spr ...

  7. spring注入参数详解

    spring注入参数详解 在Spring配置文件中, 用户不但可以将String, int等字面值注入到Bean中, 还可以将集合, Map等类型的数据注入到Bean中, 此外还可以注入配置文件中定义 ...

  8. Spring Boot 配置文件详解

    Spring Boot配置文件详解 Spring Boot提供了两种常用的配置文件,分别是properties文件和yml文件.他们的作用都是修改Spring Boot自动配置的默认值.相对于prop ...

  9. spring原理案例-基本项目搭建 02 spring jar包详解 spring jar包的用途

    Spring4 Jar包详解 SpringJava Spring AOP: Spring的面向切面编程,提供AOP(面向切面编程)的实现 Spring Aspects: Spring提供的对Aspec ...

随机推荐

  1. C#里的应用程序域AppDomain

    首先,描述一下AppDomain是什么:当一个程序集被执行时,系统就会自动为其创建一个AppDomain,每一个AppDomain属于某个进程,一个进程内可以有多个AppDomain:每个AppDom ...

  2. mysql limit的使用方法

    mysql的分页limit的使用方法大全 .取表中的n行之后的m条元组(limit n,m) ,; //取出student表中第4行后的8条元组(这里的区间是左开右闭) .取出表中前m行元素(limi ...

  3. “微信小程序” js部分注解

    1.小程序不提供获取dom的操作,而是让我们直接将事件绑定写入到组件内.区别在于bind不阻止冒泡,而catch阻止冒泡. <view id="tapTest" bindta ...

  4. vmware 安装 黑群晖

    先做一个启动盘 然后竟然启动不了 算了 不管了,去网上找个别人做好的吧 添加硬盘的时候,需要选择sata, 比如安装6.2需要这个版本的引导,就直接选中这个,因为我自己做的启动盘不管用,也不知道为嘛 ...

  5. day 52

    目录 静态文件配置 form表单默认是get请求 request方法的初识 数据库的迁移命令 静态文件配置 默认情况下所有的html文件都放在templates文件夹内 什么是静态文件 网站所使用到的 ...

  6. go语言:获取字符串长度

    go语言字符串底层由字节数组实现,使用UTF-8编码,初始化以后不能被修改 获取字符串长度 一.当字符串中所有字符都是单字节字符时,使用 len 函数获取字符串的长度 package main imp ...

  7. python 线性代数模块linalg

  8. NKOJ1472 警卫安排

    P1472警卫安排   时间限制 : 10000 MS   空间限制 : 65536 KB 问题描述 一个重要的基地被分为n个连通的区域.出于某种神秘的原因,这些区域以一个区域为核心,呈一颗树形分布. ...

  9. vue-router+iview(简单例子)

    根据上面我们已经建立好的工程项目,我们来加入路由等方法. 首先修改我们的HelloWorld.vue,加入iview的Layout组件 第二步,建立两个我们对应路由的文件 <style scop ...

  10. sending data mysql slow Mysql查询非常慢的可能原因

    1.用explain看看mysql的执行情况,可以得知,task_id扫描了近20万条数据,而且这个task_id不是索引 2.为这个task_id所在的表,将此字段添加索引后,查询就变得很快了