学习Spring框架系列(一):通过Demo阐述IoC和DI的优势所在
Spring框架最核心东西便是大名鼎鼎的IoC容器,主要通过DI技术实现。下面我通过Demo的演变过程,对比学习耦合性代码,以及解耦和的过程,并深入理解面向接口编程的真正内涵。
这个例子包括如下几个类:
- 实体类:Book,有名称、作者等属性
- BookFinder接口,定义了findAll()方法
- BookLister接口,定义了findBooks(String name)方法,以书名作为参数,并返回Book[]数组作为查找的结果
- 以及一个测试客户端BookClient,调用BookLister,来获取所需要的数据
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();
- }
- SimpleBookFinderImpl
- public 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框架系列,强烈推荐
本系列主要介绍Spring框架整体架构,Spring的核心IOC,AOP的案例和具体实现机制:以及SpringMVC框架的案例和实现机制.@pdai 相关文章 首先, 从Spring框架的整体架构和组 ...
- 深入浅出学习Spring框架(四):IoC和AOP的应用——事务配置
在前文 深入浅出学习Spring框架(一):通过Demo阐述IoC和DI的优势所在. 深入浅出学习Spring框架(三):AOP 详解 分别介绍了Spring的核心功能——IoC和AOP,光讲知识远远 ...
- 跟着刚哥学习Spring框架--创建HelloWorld项目(一)
1.Spring框架简介 Spring是一个开源框架,Spring是在2003年兴起的一个轻量级的开源框架,由Rod johnson创建.主要对JavaBean的生命周期进行管理的轻量级框架,Spri ...
- 跟着刚哥学习Spring框架--AOP(五)
AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入 ...
- 跟着刚哥学习Spring框架--通过注解方式配置Bean(四)
组件扫描:Spring能够从classpath下自动扫描,侦测和实例化具有特定注解的组件. 特定组件包括: 1.@Component:基本注解,识别一个受Spring管理的组件 2.@Resposit ...
- 跟着刚哥学习Spring框架--通过XML方式配置Bean(三)
Spring配置Bean有两种形式(XML和注解) 今天我们学习通过XML方式配置Bean 1. Bean的配置方式 通过全类名(反射)的方式 √ id:标识容器中的bean.id唯一. √ cl ...
- 跟着刚哥学习Spring框架--Spring容器(二)
Spring容器 启动Spring容器(实例化容器) -- IOC容器读取Bean配置创建Bean实例之前,必须对它进行实例化(加载启动),这样才可以从容器中获取Bean的实例并使用. Bean是S ...
- Spring框架系列(5) - 深入浅出SpringMVC请求流程和案例
前文我们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那我们如何更好的构建上层的应用呢(比如web 应用),这便是SpringMVC:Spring MVC是Spri ...
- Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)
上文,我们看了IOC设计要点和设计结构:以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的:容器中存放的是Bean的定义即Be ...
随机推荐
- Swift-字符串
1.字符串的遍历 //NSString 不支持一下字符串的遍历 let str = "我要飞的更高" for c in str.characters{ print(c) } 2.字 ...
- 【Mood-13】Android --如何从初级工程师进化为高级工程师
一 明确自我定位 现在你是初级工程师,但是你想当个高级工程师,所 以,你就要给自己定个目标,即:我是要成为高级工程师的男人.有了这个定位,并且努力朝着这个目标去努力,然后内心深处就会有一个感觉,这个 ...
- C#对话框-打开和保存对话框(转)
//打开文件 OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.In ...
- Myeclipse 突然打不开的问题
用的好好的Myeclipse今天突然打不开了,打开myeclipse提示 :an error has occurred see the log file 然后我打开日志文件,看到如下的报错信息: ! ...
- 《Python高效开发实战》实战演练——基本视图3
在完成Django项目和应用的建立后,即可以开始编写网站应用代码,这里通过为注册页面显示一个欢迎标题,来演示Django的路由映射功能. 1)首先在djangosite/app/views.py中建立 ...
- jQuery-名称符号$与其他库函数冲突
1.通过全名替代简写的方式来使用 jQuery jQuery("button").click(function(){ jQuery("p").text(&quo ...
- 洛谷 P1077 摆花
题目描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆.通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号.为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时 ...
- 真实场景中WebRTC 用到的服务 STUN, TURN 和 signaling
FQ收录转自:WebRTC in the real world: STUN, TURN and signaling WebRTC enables peer to peer communication. ...
- C基础的练习集及测试答案(提高题)
提高题:1.编写程序,随机生成一个1~10内的数,让对方猜3次.如果3次内能猜中则输出“恭喜你”:若3次内猜不中则输出正确答案.C语言中提供生成随机数的函数rand()用法:①所需头文件:#inclu ...
- 求和VII
问题 K: 求和VII 时间限制: 2 Sec 内存限制: 256 MB提交: 422 解决: 53[提交] [状态] [讨论版] [命题人:admin] 题目描述 master对树上的求和非常感 ...