第一章 Spring的核心
Spring的bean容器
1 依赖注入
Knight
package com.springinaction.knights; public interface Knight { public void embarkOnQuest(); }
BraveKnight
package com.springinaction.knights; import com.springinaction.quest.Quest; public class BraveKnight implements Knight { private Quest quest; public BraveKnight(Quest quest) { this.quest = quest; } public void embarkOnQuest() { quest.emark(); } }
Quest
package com.springinaction.quest; public interface Quest { public void emark(); }
RescueDamselQuest
package com.springinaction.quest; import java.io.PrintStream; public class RescueDamselQuest implements Quest { private PrintStream stream; public RescueDamselQuest(PrintStream stream) { super(); this.stream = stream; } @Override public void emark() { stream.println("Embarking on quest slay the dragon!"); } }
xml装配
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="knight" class="com.springinaction.knights.BraveKnight"> <constructor-arg ref = "quest"/> </bean> <bean id="quest" class="com.springinaction.quest.RescueDamselQuest"> <constructor-arg value="#{T(System).out}"/> </bean> </beans>
KnightConfig
package com.springinaction.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.springinaction.knights.BraveKnight; import com.springinaction.knights.Knight; import com.springinaction.quest.Quest; import com.springinaction.quest.RescueDamselQuest; @Configuration public class KnightConfig { @Bean public Knight knight() { return new BraveKnight(quest()); } @Bean public Quest quest() { return new RescueDamselQuest(System.out); } }
JavaConfig测试
package com.springinaction.main; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import com.springinaction.config.KnightConfig; import com.springinaction.knights.Knight; public class JavaConfigTest { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(KnightConfig.class); Knight knight = context.getBean(Knight.class); knight.embarkOnQuest(); context.close(); } }
Xml配置测试
package com.springinaction.main; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.springinaction.knights.Knight; public class XmlTest { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("knights.xml"); Knight knight = context.getBean(Knight.class); knight.embarkOnQuest(); context.close(); } }
2 AOP应用
切面
package com.springinaction.aop; import java.io.PrintStream; public class Minstrel { private PrintStream stream; public Minstrel(PrintStream stream) { this.stream = stream; } public void singBeforeQuest() { stream.println("Fa la la, the knight is so brave!"); } public void singAfterQuest() { stream.println("Tee hee hee, the brave knight did embark on a quest!"); } }
knights.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <bean id="knight" class="com.springinaction.knights.BraveKnight"> <constructor-arg ref="quest" /> </bean> <bean id="quest" class="com.springinaction.quest.RescueDamselQuest"> <constructor-arg value="#{T(System).out}" /> </bean> <bean id="minstrel" class="com.springinaction.aop.Minstrel"> <constructor-arg value="#{T(System).out}"/> </bean> <aop:config> <aop:aspect ref="minstrel"> <aop:pointcut id="embark" expression="execution(* *.embarkOnQuest(..))"/> <aop:before pointcut-ref="embark" method="singBeforeQuest"/> <aop:after pointcut-ref="embark" method="singAfterQuest"/> </aop:aspect> </aop:config> </beans>
运行结果
Fa la la, the knight is so brave!
Embarking on quest slay the dragon!
Tee hee hee, the brave knight did embark on a quest!
3 使用应用上下
Spring自带了多种类型的应用上下文。 下面罗列的几个是你最有可能遇到的。
AnnotationConfigApplicationContext: 从一个或多个基于Java的配置类中加载Spring应用上下文。
AnnotationConfigWebApplicationContext: 从一个或多个基于Java的配置类中加载Spring Web应用上下文。
ClassPathXmlApplicationContext: 从类路径下的一个或多个XML配置文件中加载上下文定义, 把应用上下文的定义文件作为类资源。
FileSystemXmlapplicationcontext: 从文件系统下的一个或多个XML配置文件中加载上下文定义。
XmlWebApplicationContext:从Web应用下的一个或多个XML配置文件中加载上下文定义。
4 bean的生命周期
在bean准备就绪之前, bean工厂执行了若干启动步骤。 上图详细描述:
1. Spring对bean进行实例化;
2. Spring将值和bean的引用注入到bean对应的属性中;
3. 如果bean实现了BeanNameAware接口, Spring将bean的ID传递给setBean-Name()方法;
4. 如果bean实现了BeanFactoryAware接口, Spring将调用setBeanFactory()方法, 将BeanFactory容器实例传入;
5. 如果bean实现了ApplicationContextAware接口, Spring将调用setApplicationContext()方法, 将bean所在的应用上下文的引用传入进来;
6. 如果bean实现了BeanPostProcessor接口, Spring将调用它们的post-ProcessBeforeInitialization()方法;
7. 如果bean实现了InitializingBean接口, Spring将调用它们的after-PropertiesSet()方法。 类似地, 如果bean使用initmethod声明了初始化方法, 该方法也会被调用;
8. 如果bean实现了BeanPostProcessor接口, Spring将调用它们的post-ProcessAfterInitialization()方法;
9. 此时, bean已经准备就绪, 可以被应用程序使用了, 它们将一直驻留在应用上下文中, 直到该应用上下文被销毁;
10.如果bean实现了DisposableBean接口, Spring将调用它的destroy()接口方法。 同样, 如果bean使用destroy-method声明了销毁方法, 该方法也会被调用。
Spring的核心模块
在Spring 4.0中, Spring框架的发布版本包括了20个不同的模块,每个模块会有3个JAR文件(二进制类库、 源码的JAR文件以及JavaDoc的JAR文件)。
Spring有20个模块组成
Spring框架由6个定义良好的模块分类组成
Spring核心容器
它管理着Spring应用中bean的创建/配置和管理。这个模块包括了Spring bean工厂,它为Spring提供了DI功能。基于bean工厂,还会有多种Spring应用上下文的实现。除了bean工厂和应用上下文,该模块还提供了许多企业服务,如E-mail/JND访问/EJB集成和调度。
Spring的AOP模块
spring对面向切面编程提供了丰富的支持。与DI一样,AOP可以帮助应用对象解藕。借助AOP,可以将遍布系统的关注点(列如事务和安全)从它们的应用的对象中解藕出来。
数据访问和集成
WEB与远程调用
Instrumentation
测试
Spring Portfollo
Spring WebFlow
Spring WebFlow建立在Spring MVC框架之上。为基于流程的会话式WEB应用提供了支持。http://projects.spring.io/spring-webflow/
Spring Web Service
提供了契约优先的Web Service模型,服务的实现都是为了满足服务的契约而编写的。http://docs.spring.io/spring- ws/site/
Spring Security
安全对于许多应用都是一个非常关键的切面,利用Spring AOP,Spring Security为Spring应用提供了声明式的安全机制。http://projects.spring.io/spring-security/
Spring Integration(整合)
许多企业级应用都需要与其他应用进行交互。Spring Integration提供了多种通用应用集成模式的Spring声明式风格实现。http://projects.spring.io/spring-integration/ 。
Spring Batch
如果需要开发一个批处理应用,可以通过Spting Bash,使用Spring强大的面向POJO的编程模型。http://projects.spring.io/ spring-batch/
Spring Data
Spring Data使得在Spring中使用任何数据库都变得非常容易。
Spring Social
Spring的一个社区网络拓展模块。
Spring Mobile
Spring Mobile是Spring MVC新的拓展模块,用于支持移动Web应用的开发。
Spring for Android
与Spring Mobile相关的是Spring Android项目。这个项目,指在通过Spring框架为开发基于Android设备的本地应用提供某些简单的支持。最初,这个项目提供Spring RestTemplate的一个可以用于Android应用之中的版本。它还能与Spring Social协作,使得原生应用可以通过Rest API进行社交网络的连接。http://projects.spring.io /spring-android/
Spring Boot
Spring极大地简化了众多的编程任务,减少甚至消除了很多版式代码。Spring Boot是一个崭新的令人兴奋的项目,它以Spring的视角,致力简化Spring本身。
Spring Boot大量依赖自动配置技术,它能消除大部分(在很多场景,甚至是其全部)Spring配置。
Spring 3.1 新特性
Spring 3.1 带来了多项有用的新特性和增强,其中有很多都是关于如何简化和改善配置的。除此之外, Spring 3.1 还提供了声明式缓存的支持以
及众多针对 Spring MVC 的功能增强。下面的列表展现了 Spring 3.1 重要的功能升级:
1.为了解决各种环境下(如开发、测试和生产)选择不同配置的问题, Spring 3.1 引入了环境 profile 功能。借助于 profile ,就能根据应用部
署在什么环境之中选择不同的数据源 bean ;
2.在 Spring 3.0 基于 Java 的配置之上, Spring 3.1 添加了多个 enable 注解,这样就能使用这个注解启用 Spring 的特定功能;
添加了 Spring 对声明式缓存的支持,能够使用简单的注解声明缓存边界和规则,这与你以前声明事务边界很类似;
3.新添加的用于构造器注入的 c 命名空间,它类似于 Spring 2.0 所提供的面向属性的 p 命名空间, p 命名空间用于属性注入,它们都是非常简
洁易用的;
4.Spring 开始支持 Servlet 3.0 ,包括在基于 Java 的配置中声明 Servlet 和 Filter ,而不再借助于 web.xml ;
改善 Spring 对 JPA 的支持,使得它能够在 Spring 中完整地配置 JPA ,不必再使用 persistence.xml 文件。
5.Spring 3.1 还包含了多项针对 Spring MVC 的功能增强:自动绑定路径变量到模型属性中;
6.提供了 @RequestMappingproduces 和 consumes 属性,用于匹配请求中的 Accept 和 Content-Type 头部信息;
7.提供了 @RequestPart 注解,用于将 multipart 请求中的某些部分绑定到处理器的方法参数中;
8.支持 Flash 属性(在 redirect 请求之后依然能够存活的属性)以及用于在请求间存放 flash 属性的 RedirectAttributes 类型。
9.除了 Spring 3.1 所提供的新功能以外,同等重要的是要注意 Spring 3.1 不再支持的功能。具体来讲,为了支持原生的 EntityManager , Spring
的 JpaTemplate 和 JpaDaoSupport 类被废弃掉了。尽管它们已经被废弃了,但直到 Spring 3.2 版本,它依然是可以使用的。但最好不要再使用它们了,因为它们不会进行更新以支持 JPA 2.0 ,并且已经在 Spring 4 中移除掉了。
Spring 3.2 新特性
Spring 3.1 在很大程度上聚焦于配置改善以及其他的一些增强,包括 Spring MVC 的增强,而 Spring 3.2 是主要关注 Spring MVC 的一个发布版
本。 Spring MVC 3.2 带来了如下的功能提升:
1. Spring 3.2 的控制器( Controller )可以使用 Servlet 3.0 的异步请求,允许在一个独立的线程中处理请求,从而将 Servlet 线程解放出来处理
更多的请求;
2. 尽管从 Spring 2.5 开始, Spring MVC 控制器就能以 POJO 的形式进行很便利地测试,但是 Spring 3.2 引入了 Spring MVC 测试框架,用于为
控制器编写更为丰富的测试,断言它们作为控制器的行为行为是否正确,而且在使用的过程中并不需要 Servlet 容器;
3. 除了提升控制器的测试功能, Spring 3.2 还包含了基于 RestTemplate 的客户端的测试支持,在测试的过程中,不需要往真正的 REST 端
点上发送请求;
4. @ControllerAdvice 注解能够将通用的 @ExceptionHandler 、 @ InitBinder 和 @ModelAttributes 方法收集到一个类中,并
应用到所有控制器上;
5. 在 Spring 3.2 之前,只能通过 ContentNegotiatingViewResolver 使用完整的内容协商( full content negotiation )功能。但是在
Spring 3.2 中,完整的内容协商功能可以在整个 Spring MVC 中使用,即便是依赖于消息转换器( message converter )使用和产生内容的
控制器方法也能使用该功能;
6. Spring MVC 3.2 包含了一个新的 @MatrixVariable 注解,这个注解能够将请求中的矩阵变量( matrix variable )绑定到处理器的方法参
数中;
7. 基础的抽象类 AbstractDispatcherServletInitializer 能够非常便利地配置 DispatcherServlet ,而不必再使用 web.xml 。
与之类似,当你希望通过基于 Java 的方式来配置 Spring 的时候,可以使用 Abstract- AnnotationConfigDispatcherServletInitializer 的子类;
新增了 ResponseEntityExceptionHandler ,可以用来替代 Default- HandlerExceptionResolver 。 ResponseEntityExceptionHandler 方法会返回 ResponseEntity<Object> ,而不是 ModelAndView ;
8. RestTemplate 和 @RequestBody 的参数可以支持范型;
9. RestTemplate 和 @RequestMapping 可以支持 HTTP PATCH 方法;
10. 在拦截器匹配时,支持使用 URL 模式将其排除在拦截器的处理功能之外。
11. 虽然 Spring MVC 是 Spring 3.2 改善的核心内容,但是它依然还增加了多项非 MVC 的功能改善。下面列出了 Spring 3.2 中几项最为有意思的新特
性:
12. @Autowired 、 @Value 和 @Bean 注解能够作为元注解,用于创建自定义的注入和 bean 声明注解;
13. @DateTimeFormat 注解不再强依赖 JodaTime 。如果提供了 JodaTime ,就会使用它,否则的话,会使用 SimpleDateFormat ;
14. Spring 的声明式缓存提供了对 JCache 0.5 的支持;
15. 支持定义全局的格式来解析和渲染日期与时间;
16. 在集成测试中,能够配置和加载 WebApplicationContext ;
17. 在集成测试中,能够针对 request 和 session 作用域的 bean 进行测试。
Spring 4.0 新特性
1. Spring 提供了对 WebSocket 编程的支持,包括支持 JSR-356——Java API for WebSocket ;
2. 鉴于 WebSocket 仅仅提供了一种低层次的 API ,急需高层次的抽象,因此 Spring 4.0 在 WebSocket 之上提供了一个高层次的面向消息的编
程模型,该模型基于 SockJS ,并且包含了对 STOMP 协议的支持;
3. 新的消息( messaging )模块,很多的类型来源于 Spring Integration 项目。这个消息模块支持 Spring 的 SockJS/STOMP 功能,同时提供了
基于模板的方式发布消息;
4. Spring 是第一批(如果不说是第一个的话)支持 Java 8 特性的 Java 框架,比如它所支持的 lambda 表达式。别的暂且不说,这首先能够让
使用特定的回调接口(如 RowMapper 和 JdbcTemplate )更加简洁,代码更加易读;
5. 与 Java 8 同时得到支持的是 JSR-310——Date 与 Time API ,在处理日期和时间时,它为开发者提供了比 java.util.Date 或 java.util.Calendar 更丰富的 API ;
6. 为 Groovy 开发的应用程序提供了更加顺畅的编程体验,尤其是支持非常便利地完全采用 Groovy 开发 Spring 应用程序。随这些一起提供的是来自于 Grails 的 BeanBuilder ,借助它能够通过 Groovy 配置 Spring 应用;
7. 添加了条件化创建 bean 的功能,在这里只有开发人员定义的条件满足时,才会创建所声明的 bean ;
8. Spring 4.0 包含了 Spring RestTemplate 的一个新的异步实现,它会立即返回并且允许在操作完成后执行回调;
9. 添加了对多项 JEE 规范的支持,包括 JMS 2.0 、 JTA 1.2 、 JPA 2.1 和 Bean Validation 1.1 。