Spring框架最核心东西便是大名鼎鼎的IoC容器,主要通过DI技术实现。下面我通过Demo的演变过程,对比学习耦合性代码,以及解耦和的过程,并深入理解面向接口编程的真正内涵。

这个例子包括如下几个类:

  • 实体类:Book,有名称、作者等属性
  • BookFinder接口,定义了findAll()方法
  • BookLister接口,定义了findBooks(String name)方法,以书名作为参数,并返回Book[]数组作为查找的结果
  • 以及一个测试客户端BookClient,调用BookLister,来获取所需要的数据

Book.java

  1. public class Book {
  2. private String name;
  3. private String author;
  4. /**
  5. * @return Returns the author.
  6. */
  7. public String getAuthor() {
  8. return author;
  9. }
  10. /**
  11. * @param author The author to set.
  12. */
  13. public void setAuthor(String author) {
  14. this.author = author;
  15. }
  16. //other getters/setters…
  17. }

BookFinder

    1. BookFinder接口
    2. public interface BookFinder {
    3. public List findAll();
    4. }
    5. SimpleBookFinderImpl
    6. public class SimpleBookFinderImpl implements BookFinder{
    7. /**
    8. * @see com.bjpowernode.spring.BookFinder#findAll()
    9. */
    10. public List findAll() {
    11. List books = new ArrayList();
    12. for(int i=0; i<20; i++){
    13. Book book = new Book();
    14. book.setName("book"+i);
    15. book.setAuthor("author"+i);
    16. books.add(book);
    17. }
    18. return books;
    19. }
    20. }

BookLister

    1. BookList接口
    2. public interface BookLister{
    3. public Book[] findBooks(String name);
    4. }
    5. BookListerImpl实现代码
    6. public class BookListerImpl implements BookLister {
    7. BookFinder finder;
    8. public BookListerImpl() {
    9. finder = new SimpleBookFinderImpl();
    10. }
    11. public Book[] findBooks(String name){
    12. List books = finder.findAll();
    13. for (Iterator iter = books.iterator(); iter.hasNext();) {
    14. Book book = (Book) iter.next();
    15. if(!book.getName().equals(name)){
    16. iter.remove();
    17. }
    18. }
    19. return (Book[])books.toArray(new Book[books.size()]);
    20. }

Spring配置ApplicationContext.xml及客户调用代码

  • Spring配置:

<bean id="bookLister" class="com.bjpowernode.spring.BookListerImpl“/>

  • 客户调用代码
  1. public static void main(String[] args) {
  2. BeanFactory beanFactory = new ClassPathXmlApplicationContext("applicationContext.xml");
  3. BookLister bl = (BookLister)beanFactory.getBean("bookLister");
  4. Book[] books = bl.findBooks("book3");
  5. if(books != null){
  6. for(int i=0; i<books.length; i++){
  7. System.out.println("书《"+books[i].getName()+"》的作者是:"+books[i].getAuthor());
  8. }
  9. }
  10. }

同样的问题:需求变更?

  • 现在,我们需要的不再是一个简单的BookFinder,我们需要的是一个能从本地文件系统中读取文件,并分析其中所包含的Book的内容,将其结果返回
  • 因为我们遵守了面向接口编程,所以,我们只需要提供第二个实现即可

FileBookFinderImpl –从文件系统读取Book的信息

  1. public class FileBookFinderImpl implements BookFinder {
  2. public List findAll() {
  3. String file = “d:/test.txt”;
  4. List books = new ArrayList();
  5. try {
  6. BufferedReader in
  7. = new BufferedReader(new FileReader(file));
  8. String line = null;
  9. while( (line = in.readLine()) != null)
  10. {
  11. String[] sp = line.split(";");
  12. if(sp.length == 2){
  13. Book book = new Book();
  14. book.setName(sp[0]);
  15. book.setAuthor(sp[1]);
  16. books.add(book);
  17. }
  18. }
  19. } catch (FileNotFoundException e) {
  20. e.printStackTrace();
  21. } catch (IOException e) {
  22. e.printStackTrace();
  23. }
  24. return books;
  25. }
  26. }

现在需要做什么?

  • 我们的客户代码调用BookLister
  • BookLister如何调用BookFinder?下面是以前初始化BookFinder的代码:

public BookListerImpl() {

finder = newSimpleBookFinderImpl();

}

  • 现在,我们必须改动这段代码:

public BookListerImpl() {

finder = newFileBookFinderImpl();

}

  • 看出问题来了吗?

严重违反面向对象的设计原则

  • BookLister接口的实现类严重依赖于BookFinder接口的实现类,这就是问题所在!
  • 我们必须在BookLister的实现类和BookFinder的实现类之间进行解偶,即解除它们之间的实现类耦合关系(依赖!)
  • 我们需实现以下目标:

    • BookLister的实现类BookListerImpl不应该依赖于特定的BookFinder接口的实现类(比如SimpleBookFinderImpl或FileBookFinderImpl)
    • BookLister的实现类,应该仅仅依赖于BookFinder接口,它不应该跟具体的功能需求实现相
    • 总之,我们不应该让BookLister和BookFinder的实现类之间互相耦合!

Spring让一切变得轻而易举

创建setter方法,为注入做好准备

  • 在BookListerImpl中定义一个setter方法

public void setFinder(BookFinder finder) {

this.finder = finder;

}

  • 把BookListerImpl构造器中的new语句注释掉

public BookListerImpl() {

//finder = new FileBookFinderImpl();

}

  • 让Spring去关心那些烦人的依赖关系吧!

Spring配置文件:ApplicationContext.xml

  • 添加BookFinder定义

<bean id="fileBookFinder" class="com.bjpowernode.spring.impl.FileBookFinderImpl“/>

  • 修改BookLister定义的配置

<bean id="bookLister" class="com.bjpowernode.spring.BookListerImpl">

<property name="finder" ref=“fileBookFinder" />

</bean>

  • 以上配置,即指定了BookListerImpl和FileBookFinderImpl之间的依赖关系,这种依赖关系,被放到了配置文件中,这样,只要需求有变更,只需要修改这种依赖关系即可,java代码本身不用任何变更

简单配置后面隐藏的内涵

  • 控制反转(Inversion of ControlIoC)与依赖注入(Dependency Injection)
  • 本来是由应用程序管理的对象之间的依赖关系,现在交给了容器管理,就叫“控制反转”或“依赖注入”。即我们需要做的事情交给了IoC容器,Spring的IoC容器主要使用DI方式实现的。不需要主动查找,对象的查找、定位和创建全部由容器管理
  • 注入,其实就是个赋值的过程,只是当我们使用时,容器已经为我们赋值好了。Spring默认在创建BeanFactory时,将配置文件中所有的对象实例化并进行注入(注入时间,可以通过default-lazy-init属性进行设置)。
  • 分析IoC容器的操作流程

实例化类。实例化fileBookFinder、BookListerImpl。

根据property标签赋值。把FileBookFinderImpl对象赋值BookListerImpl对象中的finder属性。

学习Spring框架系列(一):通过Demo阐述IoC和DI的优势所在的更多相关文章

  1. 一文深入浅出学习Spring框架系列,强烈推荐

    本系列主要介绍Spring框架整体架构,Spring的核心IOC,AOP的案例和具体实现机制:以及SpringMVC框架的案例和实现机制.@pdai 相关文章 首先, 从Spring框架的整体架构和组 ...

  2. 深入浅出学习Spring框架(四):IoC和AOP的应用——事务配置

    在前文 深入浅出学习Spring框架(一):通过Demo阐述IoC和DI的优势所在. 深入浅出学习Spring框架(三):AOP 详解 分别介绍了Spring的核心功能——IoC和AOP,光讲知识远远 ...

  3. 跟着刚哥学习Spring框架--创建HelloWorld项目(一)

    1.Spring框架简介 Spring是一个开源框架,Spring是在2003年兴起的一个轻量级的开源框架,由Rod johnson创建.主要对JavaBean的生命周期进行管理的轻量级框架,Spri ...

  4. 跟着刚哥学习Spring框架--AOP(五)

    AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入 ...

  5. 跟着刚哥学习Spring框架--通过注解方式配置Bean(四)

    组件扫描:Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件. 特定组件包括: 1.@Component:基本注解,识别一个受Spring管理的组件 2.@Resposit ...

  6. 跟着刚哥学习Spring框架--通过XML方式配置Bean(三)

    Spring配置Bean有两种形式(XML和注解) 今天我们学习通过XML方式配置Bean 1. Bean的配置方式 通过全类名(反射)的方式   √ id:标识容器中的bean.id唯一. √ cl ...

  7. 跟着刚哥学习Spring框架--Spring容器(二)

    Spring容器 启动Spring容器(实例化容器) -- IOC容器读取Bean配置创建Bean实例之前,必须对它进行实例化(加载启动),这样才可以从容器中获取Bean的实例并使用.  Bean是S ...

  8. Spring框架系列(5) - 深入浅出SpringMVC请求流程和案例

    前文我们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那我们如何更好的构建上层的应用呢(比如web 应用),这便是SpringMVC:Spring MVC是Spri ...

  9. Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)

    上文,我们看了IOC设计要点和设计结构:以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的:容器中存放的是Bean的定义即Be ...

随机推荐

  1. Python踩坑之旅其一杀不死的Shell子进程

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 坑后扩展 1.4.1 扩展知识 1.4.1 技术关键字 1.5 填坑总结 1.1 踩坑案例 踩坑的程序是个常驻的Agent类管理进程 ...

  2. Unity C# Sting.Format的学习

    String.Format (String, Object) 将指定的 String 中的格式项替换为指定的 Object 实例的值的文本等效项. String.Format (String, Obj ...

  3. 如何在数据库中导入excel文件内的数据

    如何在数据库中轻松导入excel格式的文件 1)打开sql server,找到要导入数据的数据库,右键>>任务>>导入数据 2)按照图示选择要导入的excel 3)选择导入到哪 ...

  4. java反射-使用反射获取类的所有信息

    在OOP(面向对象)语言中,最重要的一个概念就是:万事万物皆对象. 在java中,类也是一个对象,是java.lang.Class的实例对象,官网称该对象为类的类类型. Class 类的实例表示正在运 ...

  5. 处理 wait millis 60009, active 50 ,maxactive 200 异常 过程

    处理 wait millis 60009, active 50 ,maxactive 200 异常 过程2018年04月19日 16:48:46 守望dfdfdf 阅读数:1910 标签: druid ...

  6. idea(2017.3)的安装及快捷键的配置

    一  破解安装步骤: 到IntelliJ IDEA的官网:www.jetbrains.com 然后找到下载的地方,选择自己电脑所匹配的下载安装包,这里我们选择收费版的下载 接着,点击安装包进行安装,按 ...

  7. testNG测试基础一

    1.TestNG概念 TestNG:Testing Next Generation 下一代测试技术,是一套根据JUnit和Nunit思想构建的利用注释来强化测试功能的测试框架,可用来做单元测试,也可用 ...

  8. JAXB介绍二

    链接上一遍 JAXB介绍一 , 本节主要介绍解析xml的步骤, 下面的例子是在实际项目中运用的, 把它拿出来单独写一个java运行程序. 5. 测试实例 先给出我的代码结构图: 再给出要解析的Scri ...

  9. .NET中异常类(Exception)

    异常:程序在运行期间发生的错误.异常对象就是封装这些错误的对象. try{}catch{}是非常重要的,捕获try程序块中所有发生的异常,如果没有捕获异常的话,程序运行的线程将会挂掉,更严重的是这些错 ...

  10. git简易使用指南

    git简易使用指南 Git是一个分布式版本控制/软件配置管理软件,原是Linux内核开发者林纳斯·托瓦兹(Linus Torvalds)为更好地管理Linux内核开发而设计.应注意的是,这与GNU I ...