在诞生之初,Spring的主要目的是用来替代更加重量级的企业级JAVA技术,尤其是EJB。Spring提供了更加轻量级和简单的编程模型。
说白了,要明白Spring最根本的使命:简化JAVA开发。
书里只是这样简单介绍说了替代EJB。那么究其原因,需要理解一下,轻量级和重量级之间的关系, 就会明白为什么说Spring能够替代EJB。
首先要明白轻量级和重量级是一个相对的概念,主要是对应用框架使用方便性和所提供的服务特性等方面作比较。
轻量级和重量级区分:
- 加载的资源
- 侵入性
- 开发的方便程度
三个方面介绍:
加载的资源
JAVA应用程序需要JAVA EE服务器来运行应用,多数应用服务器是非常巨大且复杂的,并不容易安装和配置。
EJB启动需要大量资源、内存、CPU,把所有服务都加载进来。而Spring是可定制服务,需要什么加载什么。
侵入性(对框架的依赖性,耦合性)
EJB强制开发者写一些与框架绑定的类,使得这些类很难测试。
Spring将侵入性降到最低,它允许使用POJO进行开发。Spring并不强制实现Spring API接口或扩展Spring API类。这使得这些类方便测试。
开发的方便程度
使用重量级框架要写一些框架绑定的类,部署、运行测试都较为复杂。轻量级较为简单。
这是简单的对轻量级和重量级的一个区分,我们能看到为什么Spring能够替代EJB。
回到Spring,上面只是简单地阐述如何简化JAVA开发。
Spring采取了四种关键策略:
- 通过POJO的轻量级和最小侵入性编程
- 通过依赖注入和面向接口实现松耦合
- 通过切面和惯例进行声明式编程
- 通过切面和模板减少样板式代码
几乎Spring所做的任何事情都可以追述以上的策略。先从第一条开始。
激发POJO的潜能
我们该注意到,很多框架通过强迫应用继承它们的类或实现它们的接口从而导致应用与框架绑死。
而Spring会避免因自身API而弄乱你的应用代码。它不会强迫继承类或实现接口。通常你不会看出你使用了Spring,最坏,或许会使用Spring注解,但他依然是POJO。
我们可以看到这是一个POJO(Plain old java object,简单老式java对象),没有任何地方表明它是一个Spring组件。这种非入侵编程模型意味着这个类在Spring和非SPring应用都可以发挥作用。
而Spring通过DI来装配他们,就能实现功能。不影响原有的业务代码。
1.1.2依赖注入(DI)
DI如何实现
要知道任何一个实际意义的应用都是由多个类组成,类之间相互协作完成特定的业务逻辑。按照传统,每个对象负责管理与自己互相协作的对象的引用,这会导致高度耦合和难以测试。
可以看到构造函数中new了一个对象,意味着两个类紧密的耦合。
并且编写单元测试也很困难,你必须调用embarkOnQuest()方法调用时,embark()也会被调用。
耦合有两面性,一方面,紧密耦合的代码难以测试、难以复用、难以理解。另一方面,一定程度的耦合是必须的,没有耦合的代码什么也做不了。总而言之,耦合是必须的,但是必须谨慎管理。
通过DI,对象的依赖关系由系统中负责协调各对象的第三方组件在创建对象的时候进行设定。对象无需自行创建或管理他们的依赖关系。
具体说,由容器来进行管理,无须对象自己保存,即new具体对象。
这就是DI的精髓。
再来看例子,无须new,只需注入。
这种构造器参数传入的方式,叫做构造器注入,后面还会将更多的注入方式。
要注意,传入的Quest是一个接口,是所有想要传入的对象必须实现的接口。
要点是,该类没有和任何特定的Quest实现相耦合。对他来说,只要实现Quest接口,无论哪种实现类都可以———DI最大的收益,松耦合。这种依赖能够不影响原有代码的情况下,用不同的具体实现进行替换。
这也是spring常说的面向接口的编程,我们将需要进行的操作都放在接口中定义。这是调用者和被调用者之间的一种君子协定,即调用者只能操作接口中定义的方法,被调用者只需暴露接口中定义的方法,这对双方都是好事。
对依赖进行替换的最常用的方法就是在测试的时候使用mock实现。
将Quest注入到Knight
该如何将Quest注入? 创建应用组件之间协作的行为通常称为装配(wiring)。
下面是XML方式装配,后面也会介绍JAVA配置和自动装配。
注意构造参数如何传入(红线)。
使用JAVA来描述配置
注意红线部分。
接下来我们需要装载XML配置文件,并把应用启动起来。
观察它如何工作
Spring通过应用上下文(Application Context)装载bean定义并把它们组装起来。Spring应用上下文全权 负责对象的创建和组装。Spring自带了多种应用上下文的实现,他们之间主要的区别仅仅在于如何加载配置。
下面介绍简单一种。
首先加载XML配置文件,然后使用bean。
后面会介绍更加严谨和常用的应用上下文的装配bean的方式。
接下来介绍应用切面
1.1.3 应用切面
面向切面编程(aspect-oriented programming,AOP)允许你把遍布应用各处的功能分离出来形成可重用的组件。
说白了,切面最大的好处就在于如果需要日志、安全等功能,在不影响业务逻辑代码的情况下,依然能实现功能。让你专注业务逻辑。