学习Spring框架系列(一):通过Demo阐述IoC和DI的优势所在
来源:互联网 发布:沪港通持股数据 编辑:程序博客网 时间:2024/05/01 19:33
- 实体类:Book,有名称、作者等属性
- BookFinder接口,定义了findAll()方法
- BookLister接口,定义了findBooks(String name)方法,以书名作为参数,并返回Book[]数组作为查找的结果
- 以及一个测试客户端BookClient,调用BookLister,来获取所需要的数据
Spring框架最核心东西便是大名鼎鼎的IoC容器,主要通过DI技术实现。下面我通过Demo的演变过程,对比学习耦合性代码,以及解耦和的过程,并深入理解面向接口编程的真正内涵。
这个例子包括如下几个类:
Book.java
public class Book {private String name;private String author;/** * @return Returns the author. */public String getAuthor() {return author;}/** * @param author The author to set. */public void setAuthor(String author) {this.author = author;}//other getters/setters…}
BookFinder
BookFinder接口public interface BookFinder {public List findAll();} SimpleBookFinderImplpublic class SimpleBookFinderImpl implements BookFinder{/** * @see com.bjpowernode.spring.BookFinder#findAll() */public List findAll() {List books = new ArrayList();for(int i=0; i<20; i++){Book book = new Book();book.setName("book"+i);book.setAuthor("author"+i);books.add(book);}return books;}}
BookLister
BookList接口public interface BookLister{public Book[] findBooks(String name);}BookListerImpl实现代码public class BookListerImpl implements BookLister {BookFinder finder;public BookListerImpl() {finder = new SimpleBookFinderImpl();}public Book[] findBooks(String name){List books = finder.findAll();for (Iterator iter = books.iterator(); iter.hasNext();) {Book book = (Book) iter.next();if(!book.getName().equals(name)){iter.remove();}}return (Book[])books.toArray(new Book[books.size()]);}
Spring配置ApplicationContext.xml及客户调用代码
- Spring配置:
<bean id="bookLister" class="com.bjpowernode.spring.BookListerImpl“/>
- 客户调用代码
public static void main(String[] args) {BeanFactory beanFactory = new ClassPathXmlApplicationContext("applicationContext.xml");BookLister bl = (BookLister)beanFactory.getBean("bookLister");Book[] books = bl.findBooks("book3");if(books != null){for(int i=0; i<books.length; i++){System.out.println("书《"+books[i].getName()+"》的作者是:"+books[i].getAuthor());}}}
同样的问题:需求变更?
- 现在,我们需要的不再是一个简单的BookFinder,我们需要的是一个能从本地文件系统中读取文件,并分析其中所包含的Book的内容,将其结果返回
- 因为我们遵守了面向接口编程,所以,我们只需要提供第二个实现即可
FileBookFinderImpl –从文件系统读取Book的信息
public class FileBookFinderImpl implements BookFinder {public List findAll() {String file = “d:/test.txt”;List books = new ArrayList();try {BufferedReader in = new BufferedReader(new FileReader(file));String line = null;while( (line = in.readLine()) != null){String[] sp = line.split(";");if(sp.length == 2){… Book book = new Book();book.setName(sp[0]);book.setAuthor(sp[1]);books.add(book);}}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return books;}}
现在需要做什么?
- 我们的客户代码调用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 Control,IoC)与依赖注入(Dependency Injection)
- 本来是由应用程序管理的对象之间的依赖关系,现在交给了容器管理,就叫“控制反转”或“依赖注入”。即我们需要做的事情交给了IoC容器,Spring的IoC容器主要使用DI方式实现的。不需要主动查找,对象的查找、定位和创建全部由容器管理
- 注入,其实就是个赋值的过程,只是当我们使用时,容器已经为我们赋值好了。Spring默认在创建BeanFactory时,将配置文件中所有的对象实例化并进行注入(注入时间,可以通过default-lazy-init属性进行设置)。
- 分析IoC容器的操作流程
实例化类。实例化fileBookFinder、BookListerImpl。
根据property标签赋值。把FileBookFinderImpl对象赋值BookListerImpl对象中的finder属性。
- 学习Spring框架系列(一):通过Demo阐述IoC和DI的优势所在
- Spring IOC 学习笔记(一) IoC和DI概述
- Spring IOC 学习笔记(一) IoC和DI概述
- Spring教程系列(一)-IoC与DI
- Spring的DI和IoC
- Spring的IOC和DI
- Spring的IOC和DI
- spring的IOC和DI
- spring的IoC和DI
- spring的ioc和di
- Spring的IOC和DI
- Spring的IOC和DI
- spring 的Ioc和DI
- Spring的Ioc和Di
- Spring核心技术阐述(IOC、DI、AOP)
- Spring核心技术阐述(IOC、DI、AOP)
- Spring框架中的IOC和DI
- Spring学习笔记(一)----IoC之DI
- ArrayList 取最大值 排序
- 矩阵计算的相关问题
- C#自动登录网站(一)----WebBrowser
- AAC ADTS LATM 格式分析
- Let Me Count The Ways
- 学习Spring框架系列(一):通过Demo阐述IoC和DI的优势所在
- [转载]随机梯度下降求解矩阵分解的sample(M=UV类型分解)
- [沧海拾遗]java并发之CountDownLatch、Semaphore和CyclicBarrier
- 经典String str = new String("abc")内存分配问题
- sphinx4当中的语言模型工具和声学模型工具
- 多级页表如何节省进程页表空间
- git 创建远程分支
- linux 下部署Apache 转发域名配置
- wchar_t与char转换(总结)