天天看点

spring in action 第一章

spring in action 第一章

spring是从何而来?

spring是为了解决企业级应用开发的复杂性而创建的,使用spring可以让简单的javaBeans实现以前EJB才能完成的事情。而且spring不仅仅局限于服务器端开发,任何java应用都能在简单性,可测试性和松耦合性等方面从spring中获益。spring可以做很多事情。但归根结底,支撑spring的仅仅是少许的基本理念,所有的理念都可以追溯到spring的的最根本使命上:简化java开发。

降低java开发的复杂性,spring采取了以下四个策略:

1.基于POJO(简单java类)的轻量级和最小侵入性编程

2.通过依赖注入和面向接口实现松耦合

3.基于切面和惯例进行声明式编程

4.通过切面和模板减少样板式代码

1简化java开发

1.1激发pojo潜能

在以前的框架中我们的程序或许会被他们的规则焊死。而spring尽力避免自身api弄乱我们的代码。spring不会强迫你你实现spring规范的接口或者继承spring规范的类,相反,在基于spring构建的应用中,它的类通常没有任何痕迹表明你使用了spring。最坏的场景是,一个类或许会使用spring注解,但它仍然是POJO(简单java类)

spring in action 第一章

就像是上图的样子,在HelloWorldBean上没有任何过分的要求。这就是一个POJO(简单Java类),没有任何证据表明它是一个spring组件。spring的非侵入编程模型意味着这个类在spring应用和非spring应用中都可以发挥同样的作用。

监管POJO看起来很简单,但spring可以通过DI(依赖注入)来装配它们。让我们看看DI是如何帮助应用对象之间保持松耦合的。

1.2依赖注入

依赖注入看起来一个nb plus的词语,现在也已经演变成为一项复杂的编程技巧或设计模式理念。其实依赖注入并不像听上去那样复杂。在项目中应用DI,你会发现你的代码会变得异常简单而且更加容易理解和测试。

任何一个项目都会有两个或者更多的类组成,这些类相互协作完成特定的业务逻辑。按照一贯做法,每个对象负责管理与自己相互协作的对象的引用,这将会导致高度耦合和难以测试的代码。

spring in action 第一章

如上DamselResuingKnight只能执行DamselResuingQuest的探险任务。这两个类之间的耦合度太高了,以至于少女守护者只能做很单一的任务,他能随时保护女孩但是如果要去杀掉恶龙或者给女孩打饭呢,那这个守护者是做不到这些的。

更糟糕的是为这个类编写单元测试出奇的困难,编写测试我们要保证守护者被召唤来的时候他的方法会被调用,没有简单明了的方法可以实现这一点。

耦合具有两面性。一方面,紧密耦合的代码难以测试,难以复用,难以理解,并且典型的表现出“打地鼠”式的bug特性(修复一个bug会有更多bug出现)。另一方面耦合是不可避免的,为了完成特定任务总有类在交互,所以我们应该谨慎管理耦合。

通过DI,对象的依赖关系由系统中的第三方组件在创建对象的时候进行设定,对象无需创建或者管理它们的依赖关系。

spring in action 第一章

如上图这次我们传入一个quest他不是一个具体的探险任务,而是一个任务接口,只要实现了这个接口的探险任务BraveKnight都可以胜任。这样BraveKnight没有和任何特定探险任务有耦合,这就是DI的最大收益松耦合。

我们为BraveKnight编写一个测试是很轻松地,只需给quest一个mock实现即可

spring in action 第一章

知道了spring松耦合的原理那么我们该注入quest了有下图一个杀龙的探险任务

spring in action 第一章

可以看到这个类实现了Quest接口那么它可以注入BraveKnight,我们不仅要把这个类注入到BraveKnight里,而且要把stream注入到这个类里面。spring将创建组件之间的协作行为称为装配(wiring)。spring多种装配方式,第一种xml文件

spring in action 第一章

第二种java配置

spring in action 第一章

两种带来的DI收益是一样的,并且它们都符合上面的松耦合规则,被装配对象不知道要装配什么具体的对象,但是这些对象都有相同的接口,在装配时才知道是什么类型。

接下来要使用装配好的对象,这时需要spring应用上下文,它全权负责对象的创建和组装。spring有多种应用上下文,这里选择ClassPathXmlApplicationContext这个类加载类路径下的一个或多个xml文件,如下图

spring in action 第一章

这里可以看出来我们不知道knight的具体细节只有xml文件知道,我们不知道谁在执行任务,更不知道在执行什么样的任务。

1.3应用切面(这里大都引用原文,原文很清晰)

DI能够保证对象之间的松耦合,而面向切面允许编程允许把遍布在各处的功能分离出可重用组件

spring in action 第一章
spring in action 第一章
spring in action 第一章
spring in action 第一章
spring in action 第一章
spring in action 第一章

例子见原文这里理解原理即可

1.4使用模板消除样板式代码

有时我们会将一些代码一遍又一遍得写,比如JDBC的代码如图

spring in action 第一章
spring in action 第一章

下面是spring jdbcTemplate的代码

spring in action 第一章

模板代码可以让你只关注代码自身的职责。

spring in action 第一章

2.容纳你的bean

在spring应用中,你的应用对象生存于spring容器中,spring容器负责创建对象并且装配它们,配置和管理它们的整个生命周期,从创建到死亡(从new 到 finalize)

spring in action 第一章
spring in action 第一章

2.1使用上下文

spring in action 第一章

这里不谈web应用,剩余的上下文使用方法如下

spring in action 第一章
spring in action 第一章
spring in action 第一章

最后我们只需要用getBean方法获取类就可以了

2.1bean的生命周期

一般的java bean生命周期从new开始一直到没有引用的时候会被垃圾回收机制自动回收

相比而言spring bean生命周期要复杂得多,正确理解spring bean 生命周期非常重要,因为你或许要利用spring提供的扩展点来自定义bean的创建过程。下图展示了bean装载到spring上下文中的一个完整的生命周期过程

spring in action 第一章
spring in action 第一章

spring的功能很强大,上面所述的DI AOP 和消除版样式代码只是spring的简化java开发的基本功能,它还有许多超乎想象的功能。

spring in action 第一章
spring in action 第一章
spring in action 第一章
spring in action 第一章