第一章的主要内容介绍


  • Spring的bean容器
  • 介绍Spring的核心模块
  • 更为强大的Spring生态系统
  • Spring的新功能

 

Tips: POJO的内在含义是指那些没有从任何类继承、也没有实现任何接口,更没有被其它框架侵入的java对象。

当一个Pojo可序列化,有一个无参的构造函数,使用getter和setter方法来访问属性时,他就是一个JavaBean。

 

简化JAVA开发

Spring 目的是解决了企业级应用开发的复杂性,javabean的实现变得简单,全方面的简化java 开发的复杂性

  • 基于POJO的轻量级和最小侵入性编程;
  • 通过依赖注入和面向接口实现松耦合;
  • 基于切面和惯例进行声明式编程;
  • 通过切面和模板减少样板式代码。


激发POJO的潜能


Spring 不会强迫实现 Spring 规范的接口,并且类没有任何痕迹表明使用了Spring

eg:一个类或许有Spring 注解,但是仍然是POJO

spring stream 4 Acknowledgment 手动ack spring in action 4_构造器

如图,这是一个简单的JAVA类,POJO没有任何的地方看出使用了Spring

 

依赖注入(DI)

传统的做法是,每个对象自己负责管理与自己协作的对象的引用(依赖的对象)。 但是会导致高度耦合和难以测试。

spring stream 4 Acknowledgment 手动ack spring in action 4_构造器_02

DamselRescuingKnight在它的构造函数中自行创建了Rescue DamselQuest。这使得DamselRescuingKnight紧密地和RescueDamselQuest耦合到了一起,特定的类型。

 

并且编写测试很困难,必须保证当骑士的embarkOnQuest()方法被调用的时候,探险的embark()方法也要被调用。 (困难在于无法确保实例quest 已经被创建)

 

耦合具有两面性:一方面使得代码难以测试,复用,难以理解。另一方面,一定程度的耦合是必须的,不然完成不了任何功能(类之间不能交互和调用)。

 

通过DI 对象的依赖关系由系统中的第三方组件在创建对象的时候设定,对象无需自行的创建和管理依赖关系。依赖关系会自动交给对象,而不是由对象自己获取依赖。

spring stream 4 Acknowledgment 手动ack spring in action 4_构造器_03

BraveKnight没有自行创建探险任务,而是在构造的时候把探险任务作为构造器参数传入。这是依赖注入的方式之一,即构造器注入(constructor injection)。

并且BraveKnight 可以实现任何类型的Quest 接口,这就是DI最大的收益,松耦合

 

测试BraveKnight

spring stream 4 Acknowledgment 手动ack spring in action 4_AOP_04

mock框架Mockito去创建一个Quest接口的mock实现。通过这个mock对象,就可以创建一个新的BraveKnight实例,并通过构造器注入这个mock Quest。

调用embarkOnQuest()方法时,可以要求Mockito框架验证Quest的mock实现的embark()方法仅仅被调用了一次。

 

将Quest注入到Knight中

 

spring stream 4 Acknowledgment 手动ack spring in action 4_松耦合_05

SlayDragonQuest实现了Quest接口,这样它就适合注入到BraveKnight中去了。

 

So,现在有两个问题:

如何将SlayDragonQuest交给BraveKnight呢?

如何将PrintStream交给SlayDragonQuest呢?

 

采用XML 的方式装配bean 

spring stream 4 Acknowledgment 手动ack spring in action 4_松耦合_06

 

BraveKnight和SlayDragonQuest被声明为Spring中的bean。

BraveKnight bean来讲,它在构造时传入了对SlayDragonQuest bean的引用,将其作为构造器参数

 

基于Java 的装配

spring stream 4 Acknowledgment 手动ack spring in action 4_构造器_07

 

尽管BraveKnight依赖于Quest,但是它并不知道传递给它的是什么类型的Quest,也不知道这个Quest来自哪里。编码阶段并不知道具体的实现。

Spring通过应用上下文(Application Context)XML装载bean的定义并把它们组装起来,Spring自带了很多种上下文实现。区别仅仅是如何装配

spring stream 4 Acknowledgment 手动ack spring in action 4_松耦合_08

 

注意这个类完全不知道我们的英雄骑士接受哪种探险任务,而且完全没有意识到这是由BraveKnight来执行的。只有knights.xml文件知道哪个骑士执行哪种探险任务。

 

应用切面AOP 

DI可以让相互协作的软件保持松耦合,面向切面编程(aspect-oriented programming,AOP)允许你把遍布应用各处的功能分离出来形成可重用的组件。

日志、事务管理和安全这样的系统服务可以跨越多个系统组件。

 

spring stream 4 Acknowledgment 手动ack spring in action 4_构造器_09

如果AOP可以使得这些服务模块化,并且以声明的方法,加入到需要的组件中,使得组件会具有高内聚的特定,更加关注自身业务实现。AOP能够确保POJO的简单性

 

spring stream 4 Acknowledgment 手动ack spring in action 4_松耦合_10

 

借助AOP可以使用各种功能层去包裹核心业务层,这些层可以以声明的方式加入到切入点。

 

AOP应用

 

在之前的程序中,加入吟游诗人的角色

spring stream 4 Acknowledgment 手动ack spring in action 4_AOP_11

改变Knight 的代码

spring stream 4 Acknowledgment 手动ack spring in action 4_AOP_12

 

这个程序中,骑士对吟游诗人进行了管理,这是不符合逻辑的。骑士需要知道吟游诗人,所以就必须把吟游诗人注入到BarveKnight类中。这不仅使BraveKnight的代码复杂化了。并且吟游诗人不可复用,

利用AOP 可以将吟游诗人声明为一个切面,然后注入骑士的类中。

spring stream 4 Acknowledgment 手动ack spring in action 4_AOP_13

 

首先,需要把Minstrel声明为一个bean,然后在<aop:aspect>元素中引用该bean。

 

两种通知方法:

前置通知(before advice):(使用<aop:before>)在embarkOnQuest()方法执行前调用Minstrel的singBeforeQuest()方法。

后置通知(after advice):同时声明(使用<aop:after>)在embarkOnQuest()方法执行后调用singAfter Quest()方法。

 

模板消除样版式代码 (感觉不重要)

样板式代码的一个常见范例是使用JDBC访问数据库查询数据。举个例子,如果你曾经用过JDBC,那么你或许会写出类似下面的代码。

spring stream 4 Acknowledgment 手动ack spring in action 4_AOP_14

 

使用Spring的JdbcTemplate(利用了 Java 5特性的JdbcTemplate实现)重写的getEmploy

eeById()方法仅仅关注于获取员工数据的核心逻辑,而不需要迎合JDBC API的需求

 

spring stream 4 Acknowledgment 手动ack spring in action 4_AOP_15

 

容纳BEAN

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

容器是Spring的核心,容器使用DI构成应用组件。

Spring容器可以归为两种:

bean 工厂(由org.springframework. beans.factory.eanFactory接口定义)是最简单的容器

应用上下文(由org.springframework.context.ApplicationContext接口定义)基于BeanFactory构建,并提供应用框架级别的服务

 

使用应用上下文

无论是从文件系统还是类路径,bean 加载到bean工程的工程类似

 

spring stream 4 Acknowledgment 手动ack spring in action 4_构造器_16

 

bean的生命周期 

spring stream 4 Acknowledgment 手动ack spring in action 4_松耦合_17

spring stream 4 Acknowledgment 手动ack spring in action 4_构造器_18

 

Spring模块

 

spring stream 4 Acknowledgment 手动ack spring in action 4_AOP_19

Spring 核心容器

核心容器包括了Spring bean 工厂,提供了DI 。该模块也提供了许多企业服务,例如Email

、JNDI访问、EJB集成和调度。

 

Spring AOP 模块

帮助应用解耦

 

数据访问集成

Spring的JDBC和DAO 模块抽象了这些板式代码,简化了数据库的代码。并且提供了ORM模块

 

WEB 与远程调用

MVC 模式是一种普遍被接受的构建Web 应用的方法。Spring能够与多种MVC框架集成。

Spring远程调用功能集成了RMI(Remote MethodInvocation)、Hessian、Burlap、JAX-WS

。Spring还提供了暴露和使用REST API

 

Instrumentation

提供了为JVM添加代理(agent)的功能

 

测试

Spring 提供了测试模块,发现Spring为使用JNDI、Servlet和Portlet编写单元测试提供了一系列的mock对象实现。