在继续我们的分析之前,推荐各位静心来读一下<<Expert_OneOne_J2EE_Design_and_Development>>
第四章,
正如spring
BeanFactory

API 中描述的。这一章主要说明了设计原则,设计模式,异常处理,反射等各个方面。本来也是想着直接来分析代码,但我们应该知其然也要知其所以然,为了能加深理解Johnson创建框架的设计思路,就引入了这一部分。

从spring的核心概念IoC入手,IoC的主要含义到底是针对哪个部分来说明的?是在xml配置的对象之间的关系么?针对这个IoC,我们应该如何应用?还是应该看看spring到底是怎么应用的。

关于设计原则,比较推荐看看《敏捷软件开发》,这里面有最基本的设计原则的汇总,而expert书中都有不谋而合的理论。为了全面,还是结合了《敏捷》里面的原则,主要罗列如下:

OCP(开闭原则)

在日常的开发分析过程中,经常会遇到设计问题,我们的框架需要满足任何需求的变更,设计模式里面经常这样来说明某个设计模式如何应对变化。但是所有的设计模式实际上都是建议我们如何应对这样的变化,应该如何考虑我们的框架,于是按照《敏捷》里面的定义:对扩展开放,对更改封闭。所以对于特定的需求设计,主要需要考虑的就变成了,如何来划分扩展的部分和更改的部分。不再重复《敏捷》里面的例子,但是看完其Shape的例子,首先应该考虑的就是抽象,抽象就是我们要找的扩展和更改的界限。

在接收到一个需求的时候,我们可以不顾一切的面向对象,直接写出一些class,然后让他们互相依赖,快速的完成这些功能。那么接下来如果还有任何需求变更,就要直接修改那些类之间的依赖关系,这就如一个食物链,如果最底层的生物有什么问题,那这条链子就会受影响,当然食物链这个类比有点牵强,毕竟一种生物不会一直吃一种食物,但我们假设是那样的。类之间的直接依赖类似于这样的关系,如果我们变了最底层的依赖,可能影响它的上层,上层也有可能进一步影响上层。如果像食物链那样,每种生物有多种食物,也就是在处理依赖时,能给依赖多重选择。应该如何来考虑这个“多重选择” , 当然应该是接口。《敏捷》在Shape示例中,由过程性代码转变成OO代码,主要是加入了抽象,使得“引用”依赖接口中的“动作”,而并不是“具体对象”。这是需要特别强调的,就是不要依赖对象,要依赖动作,而java里面的interface就是“动作”的集合。

SRP(单一职责)

首先我们要明确的是何为职责,根据《敏捷》里面的定义,“引起变化的原因”。在日常开发里面,这种状况太普遍了,作为开发大军中的一员,就是这么过来的,曾经有个action类可以有3W行代码。想想这个代码行数,就知道导致它发生变化的原因多的很。如果(要是都有如果就好了)当年咱能顿悟出这么几个原则,就不说当年了,现在起就应该结合SRP和OCP来进行最初始的设计划分。

一般的web应用项目,在action之后总是按照三层的概念实现底层,一个使用struts 1/struts2的项目总是会有比较雍容的action层,但service层却仅仅是dao的封装。于是一个贫血的架构就变得家喻户晓。

但我们经常忽略那些业务上的划分,那么结合框架和业务,应该如何来考虑这种划分呢?首先一个action受http的影响(输入和输出),输入参数的各种验证,然后根据各种判断来调用某个service。从整体架构上讲,虽然是隔离了dao,但在业务层(action+service)会很臃肿。尤其是action就是个定时炸弹,承担各种职责。这个时候,就应该考虑一下设计模式来隔离一部分,划分出变化的和不变的。

LSP(Liskov替换原则)

《敏捷》定义为:子类型必须能够替换基类型。

这个定义里面有着对继承关系的强制性定义。其实在我们的日常使用中,出现比较多的问题应该是,一个类继承了很多没用的功能,这多是由于没有明确划分功能范围引起的接口方法污染。其实在一个子类不能完全替换父类的时候,就应该引起我们的警觉,是否应该按照SRP和OCP进行调整,LSP就像是一个标杆原则,总是要我们检验继承关系。

DIP(依赖注入)

《敏捷》认为所有的依赖都不应该是直接的类依赖,而应该是基于抽象。这个跟《Expert》的Achieve Loose Couple with Interfaces的出发点是一致的。上层不应该直接依赖底层,而都应依赖抽象,这里要强调两个东西,一个是何为抽象,一个是何为依赖。抽象应该是动作的抽象,那就是接口。而依赖则不仅仅是引用某个对象算是依赖,实现了某个接口也是一种依赖。

ISP(接口隔离)

在SRP的阐述中,就说起那个场景,我们的一个类里面可能不得不实现不必要的接口,这些上层接口的变化会影响实现类。在ISP中,就要求“不要强迫用户依赖不使用的方法”。接口的划分应该是基于业务需要的,如果一个interface中包含了几个业务动作,那么这不仅仅不符合SRP的原则,同时给依赖方也带来不必要的麻烦,那就是他们不得不实现不用的方法。出现这种情况的时候,我们应该考虑精细划分客户方的范围,从而针对不同的客户方,提供特别的接口动作。

以上主要是从《敏捷》中借鉴来的基本的设计原则,最开始的时候说过了,就是因为有异曲同工的基础,才考虑到直接引用《敏捷》的内容。在我看完《敏捷》之后的感觉就是,这本书要一直伴随我的左右,要深入的实践体会那些设计原则和模式。实际上这些原则都不能独立的套用,而是相辅相成的。在上面的原则描述中,都基于一个最基本的基础就是抽象。依赖抽象去实现OCP,如确认一种依赖之后,为了以后的变化,上层依赖的是接口,而底层则可能是通过策略模式等设计模式来开放给需求的变更,而这又恰恰是DIP所要求的。spring作为使用如此广泛的框架,其设计必然符合这些基本原则,才能为我们提供那些不变的依赖,和我们业务中变化的需求,那么spring中的OO设计原则又特别强调哪几个方面?

再次强调,《Expert》的chapter 4绝对值得读5遍以上,这一章摊开来就可以写一本书,其中有一些引用资料,也极有参考价值。在写这篇blog的时候,最开始特别想赶进度快点写点东西,但是再来回味《Expert》却发现以前那么一些原则,在前几年的开发里面好像没有多少顾忌的。所以就把这一章反复读了4遍,才略下本文,希望以后能够铭记和实践。

下一部分看看spring的作者Rod Johnson是参考了哪些基本原则,考虑到哪些方面来实现了伟大的spring framework?

转载请注明出处。

Dive into Spring framework -- 了解基本原理(一)的更多相关文章

  1. Dive into Spring framework -- 了解基本原理(二)--设计模式-part2

    Template模式 Template模式顾名思义是提供了一种模板,也就是针对某种业务提供了模范框架.这个在spring中是属于核心模式的,因为其ApplicationContext抽象类就是模板模式 ...

  2. Dive into Spring framework -- 了解基本原理(二)--设计模式-part1

    比较巧,自己在接触设计模式的时候,也刚开始学习spring,但可惜的是,真的仅仅在学习“用”spring,每天都沉浸在会痛快的完成spring各种配置的快乐之中,但对成长无用.其实当初就清楚,spri ...

  3. Dive into Spring framework -- 搭建spring 源码的开发环境

    spring是一个类之间依赖的管理容器,大家都知道,但我们中很多人都仅仅停留在使用的层面,但spring本身具有极大的研究价值,所以在使用了几年spring之后,还是想深入的探究一下其根源.记录于此, ...

  4. 一步步从Spring Framework装配掌握SpringBoot自动装配

    目录 Spring Framework模式注解 Spring Framework@Enable模块装配 Spring Framework条件装配 SpringBoot 自动装配 本章总结 Spring ...

  5. Spring Boot之从Spring Framework装配掌握SpringBoot自动装配

    Spring Framework模式注解 模式注解是一种用于声明在应用中扮演“组件”角色的注解.如 Spring Framework 中的 @Repository 标注在任何类上 ,用于扮演仓储角色的 ...

  6. 浅谈对Spring Framework的认识

    Spring Framework,作为一个应用框架,官方的介绍如下: The Spring Framework provides a comprehensive programming and con ...

  7. Hello Spring Framework——依赖注入(DI)与控制翻转(IoC)

    又到年关了,还有几天就是春节.趁最后还有些时间,复习一下Spring的官方文档. 写在前面的话: Spring是我首次开始尝试通过官方文档来学习的框架(以前学习Struts和Hibernate都大多是 ...

  8. 手动创建Spring项目 Spring framework

    之前学习框架一直是看的视频教程,并且在都配套有项目源码,跟着视频敲代码总是很简单,现在想深入了解,自己从官网下载文件手动搭建,就遇到了很多问题记载如下. 首先熟悉一下spring的官方网站:http: ...

  9. 转-Spring Framework中的AOP之around通知

    Spring Framework中的AOP之around通知 http://blog.csdn.net/xiaoliang_xie/article/details/7049183 标签: spring ...

随机推荐

  1. K-means聚类算法MATLAB

    以K-means算法为例,实现了如下功能 自动生成符合高斯分布的数据,函数名为gaussianSample.m 实现多次随机初始化聚类中心,以找到指定聚类数目的最优聚类.函数名myKmeans.m 自 ...

  2. maya布料预设解析

    今天做了一天布料.数值都是自己在那调整.结果发现maya自带预设,基本有些都不用调整,直接预设,效果非常不错.累死累活半天. 下来看看  预设 解析吧 ncloth新布料系统是 Maya 8.0 后新 ...

  3. sqlserver表结构查询语句

    SELECT syscolumns.name,systypes.name,syscolumns.isnullable,syscolumns.length FROM syscolumns, systyp ...

  4. Logistic Regression 模型

    逻辑回归(Logistic Regression)是机器学习中的一种分类模型,由于算法的简单和高效,在实际中应用非常广泛.本文作为美团机器学习InAction系列中的一篇,主要关注逻辑回归算法的数学模 ...

  5. mysql忘记密码怎么办?(转)

    linux下mysql忘记密码处理方法: 1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码 ...

  6. testng日志 ITestListener

    上一节我们写一个日志类 extends   TestListenerAdapter ----------TestListenerAdapter 是 ITestListener 实现的一个类 这一节,我 ...

  7. 存储库之——MongoDB

    阅读目录 一 简介 二 MongoDB基础知识 三 安装 四 基本数据类型 五 CRUD操作 六 可视化工具 七 pymongo 一 简介 MongoDB是一款强大.灵活.且易于扩展的通用型数据库1. ...

  8. logstash安装

    1.下载并安装公共签名密钥 rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch 2.创建镜像源文件:/etc/yum.rep ...

  9. Codeforces Round #408 (Div. 2) D - Police Stations

    地址:http://codeforces.com/contest/796/problem/D 题目: D. Police Stations time limit per test 2 seconds ...

  10. 并发队列ConcurrentLinkedQueue与阻塞队列LinkedBlockingQueue的区别

    1.  介绍背景 在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列. Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是Block ...