zoukankan      html  css  js  c++  java
  • 学习Spring框架系列(一):通过Demo阐述IoC和DI的优势所在

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

     

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

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

    Book.java

     

    [java] view plain copy
     
    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

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


     

    BookLister

    • [java] view plain copy
       
      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“/>

     

    • 客户调用代码

     

    [java] view plain copy
     
    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的信息

     

    [java] view plain copy
     
    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. …            
    14. Book book = new Book();  
    15. book.setName(sp[0]);  
    16. book.setAuthor(sp[1]);  
    17. books.add(book);  
    18. }  
    19. }  
    20. catch (FileNotFoundException e) {  
    21. e.printStackTrace();  
    22. catch (IOException e) {  
    23. e.printStackTrace();  
    24. }  
    25. return books;  
    26. }  
    27. }  



     

    现在需要做什么?

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

    public BookListerImpl() {

    finder = newSimpleBookFinderImpl();

    }

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

    public BookListerImpl() {

    finder = newFileBookFinderImpl();

    }

    • 看出问题来了吗?

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

    • BookLister接口的实现类严重依赖于BookFinder接口的实现类,这就是问题所在!
    • 我们必须在BookLister的实现类和BookFinder的实现类之间进行解偶,即解除它们之间的实现类耦合关系(依赖!)
    • 我们需实现以下目标:
      • BookLister的实现类BookListerImpl不应该依赖于特定的BookFinder接口的实现类(比如SimpleBookFinderImplFileBookFinderImpl
      • BookLister的实现类,应该仅仅依赖于BookFinder接口,它不应该跟具体的功能需求实现相
      • 总之,我们不应该让BookListerBookFinder的实现类之间互相耦合!

    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>

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

    简单配置后面隐藏的内涵

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

    实例化类。实例化fileBookFinderBookListerImpl

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

  • 相关阅读:
    cinder支持nfs快照
    浏览器输入URL到返回页面的全过程
    按需制作最小的本地yum源
    创建可执行bin安装文件
    RPCVersionCapError: Requested message version, 4.17 is incompatible. It needs to be equal in major version and less than or equal in minor version as the specified version cap 4.11.
    惠普IPMI登陆不上
    Linux进程状态——top,ps中看到进程状态D,S,Z的含义
    openstack-neutron基本的网络类型以及分析
    openstack octavia的实现与分析(二)原理,架构与基本流程
    flask上下文流程图
  • 原文地址:https://www.cnblogs.com/huangwentian/p/9141149.html
Copyright © 2011-2022 走看看