谈起Java 开发总是离不开各种框架,当我们在使用Java初期就被各种框架的包围着,而.Net开发就比较简单了,从WinForm到Asp.Net再到APS.Net Mvc,一气呵成,开发起来那叫一个爽,但是也带来了一些问题,比如,.Net 开发者使用微软已经封装好的类库,程序员在日常的开发过程中,都不知道自己所使用的类库有多么精妙,但是Java就不一样了,它是完全开源的,可以按照自己的需求加载适合的类库,作为开发者就可以知道大牛们写的牛叉代码,也可以看到代码的重构的美妙之处。今天我们就来谈一谈Java的Spring框架,有出入的地方希望各位给予指出。
1. 什么是Spring框架
百度百科的解释是:Spring是一个开源框架,它是为了解决企业应用开发的复杂性而创建的。从字面意思上我们知道他是为了解决开发复杂性,他是如何解决复杂性的呢,说到这问题我们就必须从Spring的特性说起了
Spring特性:
- 主要优势是分层结构,Spring框架总共有七部分组成,每一部分都可以独立拆分出来(非严格的说),分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring的核心是控制翻转(IOC)和面向切面(AOP)。简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式) 轻量级开源框架。
- 轻量:从大小与开销方面而言Spring都是轻量的,而且Spring是非侵入框架,也就是说,Spring不依赖于特定的类(大赞)。Spring的基础是控制反转(IoC)促进了低耦合
- 面向切面(AOP):在当下流程的面向对象编程的今天,AOP提出了一种新型的编程方式,Spring提供了面向切面编程的丰富的支持,分离的应用的业务逻辑和系统服务的内聚开发,比如:事务控制、异常处理等。这样我们在开发各个功能模块时就不再为出现异常我们如何捕获而烦恼了
- 容器:Spring包含并管理应用对象的配置好生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的
上面我们谈到了IoC 和AOP,那么问题来了,什么是Ioc呢?下面我们就具体谈一谈Ioc和AOP
- IoC Inversion of Control,中文意思我们翻译成控制反转,从字面意思上我们可能不太理解,我们还是具体来看图吧:
假定一个业务场景,我们声明了A、B、C、D四个模块,他们之间需要协同配置合作,在传统的开发如下图:
我们在A中需要引用ObjectB和C我们应该如何做了:
1 Public class ObjectA{ 2 ObjectB objB=new ObjectB(); 3 ObjectC objC=new ObjectC(); 4 }
上面的代码中,ObjectA类直接引用了ObjectB和ObjectC,这样创建ObjectB和ObjectC的控制权在ObjectA,这样有什么问题呢?伴随着工业级应用的规模越来越庞大,对象之间的依赖关系也越来越复杂,经常会出现对象之间的多重依赖性关系,因此,架构师和设计师对于系统的分析和设计,将面临更大的挑战。对象之间耦合度过高的系统,必然会出现牵一发而动全身的情形,耦合度太高
为了解决这个问题,我们出现了IoC思想
在ObjectA和ObjectB、C 之间添加一个中介类,这样所有的对象创建工作都是中介来做的
这样一来,如果我们将中间的 IOC容器去掉的话将是什么样的情景呢
这样一来,ObjectA\B\C\D之间就没哟了耦合,这四个部分组件可以独立开发测试,最后通过IOC整合就可以,参与开发的每一成员只要实现自己的类就可以了,跟别人没有任何关系!
所以说控制反转就是将创建对象的控制全反转,将由原来的使用者委托给了IoC容器。因为控制反转不好理解,2004年 Martin Fowler 提出了到底什么东西被反转了得到的结论是“获得依赖对象的过程被反转了",控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。
- AOP:面向切面编程
AOP是对OOP的衍生,我们现在都是面向对象编程,我们实现一个模块功能是,代码编写了如下:
public class ObjectA { public void doSomething() { connBegin(); tranBegn(); doBesiness(); tranEnd(); connEnd(); } }
在上面代码中,我们可以看到,connBegin()和connEnd()是建立链接和关闭链接功能,tranBegn()和tranEnd()是事务操作的开始和结束,而doBesiness()是真正的业务处理逻辑,相信大家也看出了问题,我们真正的业务处理逻辑被很多系统操作所包围着,这样我们就需要花时间和精力去编写也业务无关的代码,这样的编程风格也违反了设计模式的单一职责原则。
AOP 面向切面编程是横向的将各个模块切开,将模块之间公共的代码和功能集中处理,如下图所示:
将模块中各个与业务逻辑无关的系统功能抽象出来
AOP主要的功能:
将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。
当然AOP也有缺点:过于复杂;破坏封装;需要专门的编译器。