Spring实战(第3版)
[美]Craig Walls著
耿渊 张卫滨 译
2013年6月第1版
关于作者
Craig Walls也是《Spring 实战》前两个版本(Manning,2005年及2007年)的作者 。
第1章 Spring之旅
一切都要从Bean开始。
1996年12月,Sun公司发布了JavaBean 1.00-A规范。
1998年3月,Sun发布了EJB 1.0规范。
为了降低Java开发的复杂性,Spring采取了以下4种关键策略:
基于POJO的轻量级和最小侵入性编程;
通过依赖注入(DI)和面向接口实现松耦合;
基于切面和惯例进行声明式编程;
通过切面和模板减少样板式代码。
重量级框架都存在如下问题:强迫开发者编写大量冗余代码、应用与框架绑定,并且通常难以编写测试代码。
依赖注入的方式之一:构造器注入
依赖注入的最大好处:松耦合。
创建应用程序之间协作的行为通常称为装配。
Spring有多种装配Bean的方式,采用XML配置通常是最常见的装配方式。
Spring配置文件:
项目中WEB-INF\config\spring\applicationContext.xml、spring-servlet.xml
这是Spring装配Bean的一种简单方式。
Spring通过应用上下文(Application Context)装载Bean的定义并把它们组装起来。
Spring应用上下文全权负责对象的创建和组装。
依赖注入让相互协作的软件组件保持松散耦合,而AOP编程允许你把遍布应用各处的功能分离出来形成可重用的组件。
诸如日志、事务管理和安全此类的系统服务通常被称为横切关注点,因为它们总是跨越系统的多个组件。
对遍布系统的关注点服务(日志、安全、事物管理)的调用经常散布到各个组件中,而这些关注点并不是组件的核心业务
AOP使这些服务模块化,并以声明的方式将它们应用到它们需要影响的组件中去。
AOP确保POJO保持简单。
利用AOP,你可以使用各种功能层去包裹核心业务层。可以将安全、事物和日志关注点与你的核心业务逻辑相分离。
利用AOP,遍布系统的关注点覆盖在它们所影响的组件之上,促使应用组件只需关注它们的核心业务功能
许多Java API,例如JDBC,会涉及编写大量的样板式代码。
Spring旨在通过模板封装来消除样板式代码。Spring的JdbcTemplate使得在执行数据库操作时,避免传统的JDBC样板式代码成为了可能。
在Spring应用中,对象由Spring容器创建、装配和管理
Spring自带了几种容器实现,可以归为两种不同的类型。
Bean工厂是最简单得多容器,提供基本的DI支持。
应用上下文基于BeanFactory之上构建,并提供面向应用的服务,例如从属性文件解析文本信息的能力,以及发布应用事件给感兴趣的事件监听者的能力。
Spring框架自带的JAR文件
本书中是20个3.0.5,项目中是14个4.1.0
spring-aop-4.1.0.RELEASE.jar
缺***asm***.jar
spring-aspects-4.1.0.RELEASE.jar
spring-beans-4.1.0.RELEASE.jar
spring-context-4.1.0.RELEASE.jar
spring-context-support-4.1.0.RELEASE.jar
spring-core-4.1.0.RELEASE.jar
spring-expression-4.1.0.RELEASE.jar
缺***instrument***.jar
缺***instrument.tomcat***.jar
spring-jdbc-4.1.0.RELEASE.jar
spring-jms-4.1.0.RELEASE.jar
spring-orm-4.1.0.RELEASE.jar
缺***oxm***.jar
缺***test***.jar
缺***transaction***.jar
缺***web.portlet***.jar
缺***web.servlet***.jar
缺***web.struts***.jar
多spring-tx-4.1.0.RELEASE.jar
spring-web-4.1.0.RELEASE.jar
多spring-webmvc-4.1.0.RELEASE.jar
多spring-websocket-4.1.0.RELEASE.jar
Spring框架由6个定义明确的模块组成
1、核心Spring容器
2、Spring的AOP模块
3、数据访问与集成
Spring的JDBC和DAO模块封装了这些样板式代码。
4、Web和远程调用
该模块自带了一个强大的MVC框架,有助于应用提升Web层技术的松散耦合。
该框架提供了两种形式:面向传统Web应用的基于Servlet的框架和面向使用Java Portlet API的基于Portlet的应用。
5、测试
6、监测器(Instrumentation)
2007年11月,Spring团队发布了Spring框架2.5版本。Spring 2.5的重大意义在于拥抱注解驱动开发,Spring 2.5之前的版本都是采用基于XML的配置。
使用@Autowired实现基于注解驱动的依赖注入和使用@Qualifier实现细粒度的自动装配(auto-wiring)控制。
支持JSR-250注解,包括支持命名资源依赖注入的@Resource,以及对生命周期方法支持的@PostConstruct和@PreDestroy。
自动扫描使用@Component注解(或其他构造型注解)所标注的Spring组件。
一个全新的基于注解驱动的Spring MVC编程模型,极大简化了Spring Web开发。
基于JUnit 4和注解的一个新的集成测试框架。
第2章 装配Bean
在Spring中,对象无需自己负责查找或创建与其关联的其他对象。
相反,容器负责把需要相互协作的对象引用赋予各个对象。
创建应用对象之间协作关系的行为通常被称为装配(wiring),这也是依赖注入的本质。
Spring是一个基于容器的框架。但是如果你没有配置Spring,那它就是一个空容器。
从Spring 3.0开始,Spring容器提供了两种配置Bean的方式。
传统上,Spring使用一个或多个XML文件作为配置文件,而Spring 3.0还同时提供了基于Java注解的配置方式。
Spring配置文件的根元素是来源于Spring beans命名空间所定义的<beans>元素。
在<beans>元素内,你可以放置所有的Spring配置信息,包括<bean>元素的声明。
Spring的核心框架自带了10个命名空间配置。
Java自带了多种XML命名空间,通过这些命名空间可以配置Spring容器
命名空间|用途
aop|为声明切面以及将@AspectJ注解的类代理为Spring切面提供了配置元素
beans|支持声明Bean和装配Bean,是Spring最核心也是最原始的命名空间
context|为配置Spring应用上下文提供了配置元素,包括自动检测和自动装配Bean、注入非Spring直接管理的对象
jee|提供了与Java EE API的集成,例如JNDI和EJB
jms|为声明消息驱动的POJO提供了配置元素
lang|支持配置由Groovy、JRuby或BeanShell等脚本实现的Bean
mvc|启用Spring MVC的能力,例如面向注解的控制器、视图控制器和拦截器
oxm|支持Spring的对象到XML映射配置
tx|提供声明式事物配置
util|提供各种各样的工具类元素,包括把集合配置为Bean、支持属性占位符元素
第3章 最小化Spring XML配置
Spring提供了几种技巧,可以帮助我们减少XML的配置数量。
自动装配(autowiring)有助于减少甚至消除配置<property>元素和<constructor-arg>元素,让Spring自动识别如何装配Bean的依赖关系。
自动检测(autodiscovery)比自动装配更进了一步,让Spring能够自动识别哪些类需要被配置成Spring Bean,从而减少对<bean>元素的使用。
从Spring 2.5开始,最有趣的一种装配Spring Bean的方式是使用注解自动装配Bean的属性。
Spring 3支持几种不同的用于自动装配的注解:
Spring自带的@Autowired注解[项目中大量用到了];
JSR-330的@Inject注解;
JSR-250的@Resource注解。
@Autowired注解特别有趣的地方在于,我们不仅能使用它标注setter方法,还可以标注需要自动装配Bean引用的任意方法。
我们还可以直接使用@Autowired注解直接标注属性,并删除setter方法。
<context:component-scan base-package="com.poobo" /> <!-- 扫描包 -->
Spring还有另一种技巧。 <context:component-scan>元素除了完成与<context:annotation-config>一样的工作,还允许Spring自动检测Bean和定义Bean。这意味着不使用<bean>元素,Spring应用中的大多数(或者所有)Bean都能够实现定义和装配。
<context:component-scan>元素会扫描指定的包及其所有子包,并查找出能够自动注册为Spring Bean的类。base-package属性标识了<context:component-scan>元素所扫描的包。
默认情况下,<context:component-scan>查找使用构造型注解所标注的类,这些特殊的注解如下。
@Component——通用的构造型注解,标识该类为Spring组件[例如项目中的SystemLogAspect类]。
@Controller——标识将该类定义为Spring MVC controller[例如项目中的ConfigListCtr类、EqGamesInfoCtr类、EquipmentCtr类、EquipmentlConfigListCtr类、InitSysCtr类、ResourcesConfigCtr类、ResourcesCtr类、SysAccountCtr类]。
@Repository——标识将该类定义为数据仓库[例如项目中的ConfigListDaoImpl类、EqGamesInfoDaoImpl类、EquipmentConfiglistDaoImpl类、EquipmentDaoImpl类、ResourcesConfigDaoImpl类、ResourcesDaoImpl类、SysAccountDaoImpl类、SysLoginDaoImpl类]。
@Service——标识将该类定义为服务[例如项目中ConfigListServiceImpl类、EqGamesInfoServiceImpl类、EquipmentConfigListServiceImpl类、EquipmentServiceImpl类、ResourcesConfigServiceImpl类、ResourcesServiceImpl类、SysAccountServiceImpl类、SysLogServiceImpl类]。
第4章 面向切面的Spring
在软件开发中,分布于应用中多处的功能被称为横切关注点(cross-cutting concerns)。将这些横切关注点与业务逻辑相分离正是面向切面编程(AOP)所要解决的。
切面实现了横切关注点(跨越多个应用对象的逻辑)的模块化
切面提供了取代继承和委托的另一种选择。
横切关注点可以被模块化为特殊的类,这些类称为切面。
描述切面的常用术语有通知(advice)、切点(pointcut)和连接点(join point)。
在AOP术语中,切面的工作被称为通知。
Spring切面可以应用5种类型的通知。
Before——在方法被调用之前调用通知。
After——在方法完成之后调用通知,无论方法执行是否成功。
After-returning——在方法成功执行之后调用通知。
After-throwing——在方法抛出异常之后调用通知。
Around——通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。
连接点是在应用执行过程中能够插入切面的一个点。
一个切面并不需要通知应用的所有连接点。切点有助于缩小切面所通知连接点的范围。
切面(Aspect)是通知和切点的结合。通知和切点共同定义了关于切面的全部内容——它是什么,在何时和何处完成其功能。
引入(Introduction)允许我们向现有的类添加新方法或属性。
织入(Weaving)是将切面应用到目标对象来创建新的代理对象的过程。
AOP框架形成了现在的三足鼎立的格局:
AspectJ
JBoss AOP
Spring AOP
Spring提供了4种各具特色的AOP支持:
基于代理的经典AOP;
@AspectJ注解驱动的切面;
纯POJO切面;
注入式AspectJ切面(适合Spring各版本)
Spring的AOP配置元素简化了基于POJO切面的声明
AOP配置元素|描述
<aop:advisor>|定义AOP通知器
<aop:after>|定义AOP后置通知(不管被通知的方法是否执行成功)
<aop:after-returning>|定义AOP after-returning通知
<aop:after-throwing>|定义AOP after-throwing通知
<aop:around>|定义AOP环绕通知
<aop:aspect>|定义切面
<aop:aspectj-autoproxy/>|启用@AspectJ注解驱动的切面
<aop:before>|定义AOP前置通知
<aop:config>|顶层的AOP配置元素,大多数的<aop:*>元素必须包含在<aop:config>元素内
<aop:declare-parents/>|为被通知的对象引入额外的接口,并透明地实现
<aop:pointcut>|定义切点
项目中用到了:
<!-- 配置参与事务的类 -->
<aop:config>
<aop:pointcut id="allTestServiceMethod" expression="execution(* com.poobo.*.service.*.*(..))"/>
<aop:advisor pointcut-ref="allTestServiceMethod" advice-ref="transactionAdvice" />
</aop:config>
<aop:aspectj-autoproxy/> <!-- aop切面注解 -->
<aop:aspectj-autoproxy proxy-target-class="true" /> <!-- 通知spring使用cglib而不是jdk的来生成代理方法 AOP可以拦截到Controller -->
第5章 征服数据库
5.1 Spring的数据访问哲学
服务对象本身并不会处理数据访问,而是将数据访问委托给DAO。DAO接口确保其与服务对象的松耦合
5.1.1了解Spring的数据访问异常
可能导致抛出SQLException的常见问题包括:
应用程序无法连接数据库;
要执行的查询有语法错误;
查询中所使用的表和(或)列不存在
试图插入或更新的数据违反了数据库的完整性约束。
JDBC的异常体系过于简单了,Hibernate的异常体系是其本身所独有的。我们需要的是,数据访问异常要具有描述性而且又与特定的持久化框架无关。
5.1.2数据访问模块化
Spring将数据访问过程中固定的和可变的部分明确划分为两个不同的类:模板(template)和回调(callback)。模板管理过程中固定的部分,而回调处理自定义的数据访问代码。
Spring的DAO模板类负责通用的数据访问功能。对于应用程序特定的任务,则会调用自定义的DAO回调对象。
5.1.3使用DAO支持类
5.2配置数据源
5.2.1使用JNDI数据源
5.2.2使用数据源连接池
5.2.3基于JDBC驱动的数据源
5.3在Spring中使用JDBC
5.3.1应对失控的JDBC代码
5.3.2使用JDBC模板
5.4在Spring中集成Hibernate
一些可用的框架提供了延迟加载(Lazy loading)、预先抓取(Eager fetching)、级联(Cascading)这样的服务。这些服务的通用名称是对象/关系映射(ORM)。在持久层使用ORM工具,可以节省数千行的代码和大量的开发时间。
5.4.1Hibernate概览
5.4.2声明Hibernate的Session工厂
使用Hibernate的主要接口是org.hibernate.Session。Session接口提供了基本的数据访问功能,如保存、更新、删除以及从数据库加载对象的功能。通过Hibernate的Session接口,应用程序的DAO能够满足所有的持久化需求。
获取Hibernate Session对象的标准方式是借助于Hibernate的SessionFactory接口的实现类。除了一些其他的任务,SessionFactory主要负责Hibernate Session的打开、关闭以及管理。
如果你选择在XML中定义对象与数据库之间的映射,那么需要在Spring中配置LocalSessionFactoryBean:
本书中是hibernate3,项目中是hibernate4
<!-- sessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<!-- 用于测试,在控制台实现sql语句 -->
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop>
</props>
</property>
<!-- 加载hibernate的映射文件-->
<property name="mappingDirectoryLocations">
<list>
<value>classpath:/com/poobo/entity/hbm*</value>
</list>
</property>
</bean>
在配置LocalSessionFactoryBean时,我们使用了3个属性。
dataSource属性装配了一个DataSource Bean引用。
多mappingDirectoryLocations缺mappingResources属性装配了一个或多个的Hibernate映射文件,在这些文件中定义了应用程序的持久化策略。
hibernateProperties属性配置了Hibernate如何进行操作的细节。
如果你更倾向于使用注解的方式来定义持久化,那需要使用AnnotationSessionFactoryBean来代替LocalSessionFactoryBean[项目中持久化域对象是通过XML文件进行配置的]。
5.4.3构建不依赖于Spring的Hibernate代码
5.5 Spring与Java持久化API
5.5.1配置实体管理器工厂
5.5.2配置基于JPA的DAO
第7章 使用Spring MVC构建Web应用程序
7.1 Spring MVC起步
7.1.1跟踪Spring MVC的请求
7.1.2搭建Spring MVC
7.2编写基本的控制器
7.3处理控制器的输入
7.4处理表单
7.5处理文件上传