第一章 Spring核心

spring核心

spring为企业版开发提供了很丰富的功能,但这些功能底层都依赖于他的两个核心特性,就是依赖注入(DI)和面向切面编程(AOP)

spring的承诺和理念是全方位的简化Spring开发

spring是如何简化spring开发的

spring采取了下面四个策略

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

几乎spring的所有事情都可以做到上述的一条策略或者多条策略

依赖注入

依赖注入这个词理解起来好像很困难,现在已经演变成一种复杂的编程技巧或者设计模式理念,但是使用起来往往很简单,在你的项目中使用依赖注入(DI)往往可以是你的代码更简洁和容易测试

快速认识DI(依赖注入)

DI(依赖注入)是如何实现的

  • 按照传统做法,每个对象负责他自己,或者他所依赖的对象,这将会造成代码的高度耦合和难以测试
  • 耦合具有两面性,一方面高度耦合的代码将难以理解,难以复用,难以测试,并且代码会出现打地鼠的特性(修复一个bug将会出现更多的bug).另一方面,完全不耦合的代码将无法实现任何功能,类之间必须相互交互,总而言之,耦合时必须的,但是必须小心管理
  • 通过DI(依赖注入),对象的依赖关系将由系统中负责协调各对象的额第三方组件在创建对象时进行设定.对象无需自行创建或者管理他们之间的依赖关系
DI(依赖注入)的方式(其中一种)
  • 构造器注入:在调用构造函数的时候作为构造器参数传入,如果一个对象只以接口(而不是具体实现或者初始化过程),那么这种依赖就能在对象不知情的情况下,用不同的具体实现方式进行替换.(对依赖进行替换的最常见方式是在测试的时候使用mork对象替换)

创建应用组件之间的协作行为称为装配(waring),
spring有多种进行装配的方式,采用XML是常见的一种方式

不管是何种装配方式,DI的收益都是相同的.spring通过它的配置,能够了解这些组装成分是如何装配起来的.这样就可以在不改变的类的情况下,改变他们的依赖关系

DI的工作方式

    Spring通过应用上下文(Application Context)装在bean定义并将他们组装起来,Spring全权负责对象的创建和组装.
Spring自带多种Application Context的实现,他们的区别仅仅在于如何加载配置

应用切面

DI能够让相互协作的软件达到松耦合,而面向切面编程允许你把遍布应用各处功能分离出来当做可重用的组件

面向软件编程往往被定义为促使软件系统关注点分离的一项技术,系统往往由不同的组件组成,每一个组件负责一部分功能,但是某些组件,除了实现自己的核心功能外,还需要承担一部分其他职责,比如安全,日志,事务管理组件,这些系统组件通常被称为横切关注点,因为他们会跨越多个系统组件.

横切关注点分散到各个组件的弊端
  • 实现系统关注点的代码将重复的出现在多个组件中,这意味着你要改变关注点的逻辑,必须修改模块中的相关功能实现.
  • 组件会因为那些与自己核心功能无关的代码而变得混乱
AOP能够使这些模块简单化,并且以声明的方式将他们应用到他们需要应用的组件中去.
AOP的优点
  • 这些组件具有更高的内聚性,并且只需要关注自己本身的业务
  • 借助 AOP可以使用各种功能层去包裹核心业务层,核心层本身甚至不知道他们的存在,这是一个十分强大的理念,可以将安全,日志关注点与核心业务逻辑相分离
AOP的使用
  • Spring的AOP命名空间可以将bean声明为切面,将某个关键地方设置成切点,针对切点可以通过AOP设置前置通知(让事件在切点之前执行),后置通知(让事件在切点之后执行)
  • SpringAOP可以做很多有意义的事情,比如基于SpringAOP实现声明式事务和安全.

Spring简化java开发的其他方式

使用模板相处样板式代码

在我们的日常中,经常实现通用和简单的任务,一遍一遍的写样板式的代码,比如JDBC连接数据库
,JMS,JNDI使用REST服务通常也涉及大量的业务代码.

Spring旨在通过模板封装来消除样板代码
比如Spring的JdbcTemplan方法可以将连接关闭数据库的样板式代码封装起来,让我们将关注重点放在代码的实际作用上,而不需要其余的繁琐步骤

现在我们知悉了Spring通过面向POJO编程,DI,切面和模板技术来简化Java开发的复杂性,比如在基于XML的配置文件中来配置bean和切面,但是这些文件在那里被加载,他们被加载到哪里去了,Spring容器是所有bean生存的地方

容纳你的bean

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

容器是 Spring框架的核心
  • Spring容器通过DI管理构成应用的组件,他们会创建相互协作的组件的关联.(这些对象更简单干净,更易于理解,更易于重用并且更容易进行单元测试)
  • Spring容器并不是只有一个.Spring自带了多个容器实现,总的包括两种类型
    1. bean工厂(由org.springframwork.beans.factory.eanFactory接口定义)是最简单的容器,提供最基本的支持.
    2. 应用上下文(由org.springframework.context.ApplicationContext)基于beanFactory构建,并提供应用框架级别的服务,例如从属性文本解析文本信息以及发布应用事件给感兴趣的事件监听者.
虽然可以在着两者之间任选一种,但是bean工厂对于大多数应用来说太低级了,因此,应用上下文比bean工厂更受欢迎
使用应用上下文
  • AnnotationConfigApplicationContext:从一个或多个基于Java的配置类中加载Spring应用上下文
  • AnnotationConfigWebApplicationContext:从一个或多个基于java的配置类中加载Spring Web应用上下文
  • classPathXmlApplicationContext:从类路径的一个或多个Xml文件中加载上下文定义,把应用上下文的定义文件当做类资源
  • FileSystemXmlapplicationContext:从文件系统下的一个或多个Xml文件中加载上下文定义
  • XmlWebApplicationContext:从web应哟下的一个或多个Xml配置文件中加载上下文定义
当讨论基于web的soring应用时,我们会对ApplicationConfigWebApplicationContext 和XmlWenApplicationContext进行更详细的讨论,现在我们简单的使用FileSystemXmlApplication从文件系统中加载应用上下文或者使用ClassPathXmlApplicationContext从类路径中加载上下文.
    例如:如何加载一个FileSystemXmlapplicationContext:
    
    ApplicationContext context = new fileSystemXmlapplicationContext("c:knight.xml");
    
    
    类似的,使用classPathXmlApplicationContext从类路径的一个或多个xml文件中加载上下文定义
    
    ApplicationContext context = new classPathXmlApplicationContext("knight.xml");
    
    
    如果想从java配置中加载应用上下文,就使用AnnotationConfigApplicationContext
    
    ApplicationContext context = new AnnotationConfigApplicationContext(com.springinaction.kinghtrs.comfig.kinghtConfig.class);
    在这里没有指定spring加载上下文所必需的的xml文件,AnnotationConfigApplicationContext通过一个配置类加载bean
    
    应用上下文就绪之后,我们就可以调用getBean()方法从Spring中获取bean.

现在已经了解了如何创建Spring容器,让我们对容器中的bean声明周期进一步探讨

bean的生命周期

在传统的java应用程序中,bean的声明周期很简单,使用java关键字new进行bean实例化,然后该bean就可以使用了,一旦bean不再使用,则由java进行垃圾回收

相比之下,Spring的生命周期就复杂的多,正确理解SpringBean的生命周期很重要,因为你或许要利用Spring提供的扩展点来自定义bean的创建过程

bean的生命周期过程
  1. 实例化
  2. 填充属性
  3. 调用BeanNameAware的setBeanName()方法
  4. 调用BeanFactoryAware的setBeanFactoy()方法
  5. 调用ApplicationContextAware的setApplicationContext()方法
  6. 调用BeanPost的Processor的预初始化方法
  7. 调用InitializingBean的afterPropertiesSet()方法
  8. 调用自定义的初始化方法
  9. 调用BeanPost的Processor的初始化后方法
  10. bean就可以使用了
  11. 容器关闭
  12. 调用disposableBean的destroy()方法
  13. 调用自定义的销毁方式

就像这样,在bean准备就绪之前,bean工厂执行了若干启动步骤,下面对上述内容进行详细描述

  1. Spring对Bean进行实例化
  2. Spring将值和bean的引用注入到bean对应的属性中
  3. 如果bean实现的BeanNameAware接口,Spring将Bean的Id传入setBeanName()方法
  4. 如果bean实现了BeanFactoryAware接口,那么就调用setBeanFactory方法将BeanFactory容器实例传入
  5. 如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法将将bean所在的应用上下文传入进来
  6. 如果bean实现了BeanPostProcessor接口,Spring将调用他们的postProcessBeforeInitialization()方法
  7. 如果bean实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet方法.类似的
  8. 如果bean使用了initmethod声明了初始化方法,那么该方法也会被调用
  9. 如果bean实现了BeanPostProcaess接口,Spring将会调用他们的PostProcessAfterInitialization()方法
  10. 此时bean已经准备就绪,可以被应用程序使用了,他将一直驻留在应用上下文中,直到应用上下文被销毁
  11. 如果bean实现了disposanleBean接口,Spring将调用他的destroy()方法.
  12. 如果bean使用destroymethod的销毁方法,那么该方法也会被调用
现在已将学会了如何创建和加载一个Spring容器,但是一个空的容器并没有任何价值,在你放东西进去之前,他什么东西都没有,为了从Spring的DI中收益,我们必须将Spring对象装配进Spring容器中,这点将会在bean装配中进行探讨


Spring体系结构

Spring框架的基本组成部分和最新版本Spring发布的新特性

从前面看来,Spring从DI,AOP,和消除样板式代码来简化企业级的java开发,但是Spring的实际功能远超乎你的想象

在Spring框架内,会有很多简化java开发的多种方式,但在Spring框架之外还存在一个构建在核心框架之外的庞大生态圈,他将Spring扩展到其他不同领域,例如Web服务,REST,移动开发以及NOSQL

Spring模块

Spring的发布版本有20多个不同的模块,每个模块有3个JAR文件(二进制类库,源码,javadoc文件),这些模块依据所属的功能具体可分为六类

这些模块为java企业版开发停工了所需的一切,但是你也不必将应用建立在整个Spring框架之上,你可以自由选择适合自身需求的Spring模块;当spring不能满足需求时,完全可以其他选择.Spring甚至提供了与其他第三方框架和类库的集成点.

Spring六个模块分类
  1. Spring核心容器
  • bean
  • Core
  • Context
  • Expression
  • Context support
  1. 面向切面编程
  • AOP
  • Aspects
  1. 数据访问与集成
  • JDBC
  • Transaction
  • ORM
  • OXM
  • Messageing
  • JMS
  1. Web与远程调用
  • Web
  • Web servlet
  • WebSocket
  • WebProtlet
  1. Instrumentation
  • Instrument
  • Instrument Tomcat
  1. 测试
  • Test

一 Spring核心容器
容器是Spring框架最核心的部分,他管理着Spring应用中的bean的创建,配置和管理.在该模块中,包括Spring Bean工厂,他为Spring提供了DI的功能,基于bean工厂,有多种Spring应用上下文的实现,每一种都提供的配置Spring的不同方式

除了bean工厂和应用上下文,该模块也提供了许多企业服务,例如E-mail,JNDI访问,EJB集成的调度.

所有的Spring模块都构建于核心容器之上.当你配置应用时,其实就隐式的使用了这些类.Spring核心模块将会贯穿Spring技术


二 Spring的AOP模块
在AOP模块中,Spring对面对切面编程提供了丰富的支持,这个模块是Spring应用系统中开发切面的基础.与DI一样,AOP可以帮助应用对象解耦.借助AOP,可以将遍布系统的关注点(例如安全和事务管理)从他们所应用的对象分离出来

三 数据访问与集成
比如Spring的JDBC和DAO模块抽象了JDBC的样板式代码,使数据库代码简单明了,还可以避免因关闭数据库资源失败而引起的问题
Spring提供了ORM模块,Spring的ORM模块建立在对DAO层的支持之上,并为多个ORM框架提供了一种构建DAO的简便方式,Spring并没有提供自己的ORM解决方案,而是许多流行的ORM框架进行的集成,包括Hibernate,javaPersisterce API,java Date Object 和iBates SQL Maps,Spring的事务管理支持所有的ORM框架以及JDBC
本模块同样包含了在JMS之上构建的抽象层,他会使用消息以异步的方式与其他项目集成.从Spring3.0开始,本模块还包含从像映射到XML的特性,这原本是Speing Web Service项目的一部分

四 Web与远程调用

MVC(Model-View-Controller)模式是一种普遍被接受的构建Web应用的方法,用来将界面逻辑和业务逻辑分离.java从来不缺少MVC框架,Apache的Struts,JSF,WebWork和Tapestry都是流行的可选MVC框架

虽然Spring能够与多种优秀的MVC框架进行集成,但他的Web和远程调用模块自带了一个强大的MVC框架,有助于在Web层提升应用的松耦合水平
除了面向用户的Web应用,该模块还提供了多种构建与其他应用交互的远程调用方案,Sping远程调用功能集成了RMI,Hession,burlap JAX-WX,同时Spring还自带了一个远程调用框架:HTTP invoker,Spring还提供和暴露和使用REST API的良好支持

五 Instrumenantion

Spring的Instrumenantion模块提供了为JVM提供代理(agent)的功能,具体来说,他为Tomcat提供了一个织入代理,能够为Tomcat传入类文件,就像这些文件是被类加载器加载的一样

但这个模块所提供的Instrumenation所使用的场景十分有限


六 测试
鉴于开发者自测的重要性,Spring提供了测试模块亦致力于Spring应用的测试

通过该模块,Spring未使用JNDI,servlet和Portlet编写单元提供了一系列的mork对象实现,对于集成测试,该模块为加载Spring上下文的bean集合与应用上下文中的bean的交互提供了支持



Spring Portfolio

事实上Spring远不是Sprinf框架所下载的那些,如果仅仅停留在核心的Spring框架层面,我们将错过Spring Portfolio所提供的巨大财富,整个Spring Portfolio包括多个构建于核心Spring框架之上的框架和类库,整个Spring Protfolio几乎为每一个领域的java开发提供了编程模型

  • Spring Web Flow

Spring Web Flow建立与SpringMVC框架之上,他为基于流程的会话式WEB应用(购物车或向导功能)提供了支持

  • Spring Web Service

虽然核心的Spring框架提供了Spring bean以声明的方式发布Web service的功能,但是这些服务是基于一个具有争议性的架构(拙劣的契约后置模型)之上构建的,这些服务的契约由bean的接口来决定

  • Spring Security

安全对于许多应用都是一个非常关键的切面.利用Spring AOP,Spring Security为Spring应用提供声明式的安全机制,你将会在后面看到如何给Web层添加Spring Security功能

  • Spring integration

Spring Integration 提供了多种通用应用集成模式的Spring声明式实现

  • Spring Batch

当我们需要对数据进行大量操作时,没有任何技术可以比批处理更适合这种场景,如果开发一个批处理应用,你可以通过Spring Batch,使用Spring强大的面向POJO的模型

  • Spring Date

    SpringDate使得在Spring中使用任何数据库都变得很容易,尽管关系型数据库使用多年,但是现代化的应用正在认识到并不是所有的应用都适合放在一张表的行和列中,一种新的数据库种类,NoSQL数据库,提供了使用数据的新方法,这些方法比传统型数据库更合适

    不管你使用文档数据库,如MongoDB ,图数据库,如NEO4J,还是传统的关系项数据库,SpringDate都为持久化提供了一种简单的编程模型,这包括为多种数据库类型提供了一种自动化的Ropository机制,他负责为你创建Ropository的实现

  • Spring Social

这是Spring中一个网络扩展模块,例如twtter或者facebook,Spring Social更多的是关注连接(conn),它能够帮助你通过REST API连接Spring应用

  • Spring Mobbile

Spring Mobbile是Spring MVC的扩展模块,用于支持移动web开发

  • Sprng for Android

这个项目旨在通过Spring框架为开发基于Android设备的本地应用提供某些简单的支持,最初,这个项目提供了SpringRestTemplate的一个可以用于Android应用之中的版本,他还能与Spring Social合作,使得原生应用可以通过REST API进行社交网络的连接

  • Spring Boot

Spring极大地简化了众多编程任务,减少甚至消除了很多样板式代码,springBoot是个令人兴奋的项目,他以Spring的视角,致力于简化Spring本身

Spring boot大量依赖自动配置技术,它能够消除大部分(在很多场景中,甚至是全部)的Spring配置,他还提供多个Starter项目,不管你使用Maven还是Gradle,这都能减少Spring项目构建文件的大小

spring新特性

spring3.1新特性

Spring3.1带来了多项有用的新特性和增强,其中很多都是关于如何简化和改善配置的,除此之外,Spring3.1还提供了声明式缓存的支持和针对SpringMvc的功能增强

以下展示Spring3.1重要的功能升级
  • 为了解决各种环境下(如开发,测试,和生产)选择不同配置的问题,Spring3.1引入了环境profile功能,就能根据应用部署在什么环境中选择相应的数据源bean
  • 在Spring3.0基于java配置之上,Spring3.1添加了多个enable注解,这样就能使用这个注解启用Spring特定功能
  • 添加了Spring对声明式缓存的支持,能够通过简单的注解声明缓存边界和规则,这点和声明事务边界很相似
  • 新添加的用于构造器注入的c命名空间,它类似于Spring2.0所提供的面向属性的p命名空间,p命名空间用于属性注入,他们都是简洁易用的
  • Spring开始支持Servlet3.0,包括在基于java的配置中声明Servlet和Filter,而不再借助于Web.xml
  • 改善了Spring对JPA的支持,使得它能够在Spring中完整的配置JPA,不必再使用spersistence.xml
Spring3.1多项对SpingMVC的技术增强
  • 自动绑定路径变量到模型属性中
  • 提供了@RequestMappingproduces和consumes属性,用于匹配请求中的 Accpect和Content-Type头部信息;
  • 提供了@Requestpart注解,用于将multipart请求中的某些部分绑定到处理器的方法参数中
  • 支持Flash属性(在redircet请求之后仍然存活的属性)以及用于在请求间存放flash属性的RedircetAttributes类型

Spring3.2新特性

Spring3.2是主要关注SpringMVC增强的一个发布版本
  • Spring3.2中的控制器(controller)可以使用Servlet3.0的异步请求,允许在一个独立的线程中完成请求,从而将Servlet线程解放出来处理更多的请求;
  • Spring3.2引入了SpringMvc测试框架用于微控制器编写更丰富的测试,断言他们作为控制器的行为是否正确,而且在使用的过程中不需要编写Servlet容器
  • 除了提升控制器的测试功能,Spring3.2还包含了基于RestTemplant的客户端的测试支持,在测试的过程中,不需要往真正的REST端点上发送请求
  • @ControllerAdvice注解能够将通用的@ExceptionHandler,@InitBinder和@ModelAttributes方法收集到一个类中,并应用到所有的控制器上
  • 在Spring3.2后,完整的内容协商功能可以在整个SpringMVC中使用,即时是依赖消息转换器(Message concover)使用和产生内容的控制器方法也是用此功能
  • Spring3.2包含一个新的@MatrixVariable注解,这个注解能够将请求中的矩阵变量绑定到处理器的方法去参数中
  • 基础的抽象类AbstractDispatcherServletInitializer能够非常便利地配置DispatcherServlet,而不必使用web.xml,与之相似,当你希望用基于java的方式来配置Spring的时候AbstractAnnotationConfigDispatcherServletInitializer的子类
  • 新增了ResponseEntityExceptionHandler,可以用来代替DefaultHandklerExceptionResolve,ResponseEntityExceptionHandler方法会返回ResponseEntity对象而不是ModelAndView
  • RestTemlate和RequestBody的参数可以支持泛型
  • RestTemlate和RequestMapping可以支持HTTP Patch 方法
  • 在拦截器匹配时,支持使用URL模式将其排除在拦截器的处理功能之外
虽然SpringMVC是Spring3.2更新的核心内容,但是他依然增加了许多非MVC的功能
  • @Autowired @Value和@Bean注解能够作为元注解,用于创建自定义的注入和bean声明
  • @DateTimeFormat不再强依赖JodaTime,如果提供了JodeTime,就会使用他,否则的话,就要使用simpleTimeFormat
  • Spring的声明式缓存提供了对JCache0.5的支持
  • 支持定义全局的格式来解析和渲染日期和时间
  • 在集成测试中,能够配置和加载WebApplicationContext
  • 在集成测试中,能够针对Request和session作用域的bean进行测试

Spring4.0新特性

在Spring4.0中包含很多令人兴奋的特性

  • Spring提供了对WebSocket编程的支持,包括支持JSR-356 -----Java API for WebSocket
  • 鉴于WebSocket只提供了一种低层次的API,急需高层次的抽象,因此Spring4.0在Wev Socket之上提供了一层高层次的面向消息的编程模型,该模型基于SockJS,并且包含了对STOMP协议的支持
  • 新的消息(messaging)模块,很多类型来源于Spring Integration项目,这个消息模块支持Spring的Socket/STOMP功能,同时提供了基于模板的方式
    发布消息
  • Spring是第一批支持java8特性的java框架,比如他所支持的lambda表达式,这能让特定的回调接口(比如RowMapping和JdbcTemplant)更加简洁易读
  • 与Java8同时得到支持的是JSR-310-----Date和TimeAPI ,在处理日期和时间时,他为开发者提供了比java.unit.Date和java.unit.calendar更丰富的API
  • 为Groovy开发的应用程序提供了更加顺畅的编程体验,尤其是支持非常便利地完全采用Groovy开发Spring应用程序,随这些一起提供的是来自Grails的BeanBuilder,借助他能够通过Groovy配置Spring应用
  • 通过条件化创建bean的功能,在这里只有开发人员定义的条件满足时,才会创建所声明的bean
  • Spring4.0包含了Spring RestTemplant的一个新异步实现,他会立即返回并且允许在执行操作后回调
  • 添加了对多项JEE规范的支持,包括JMS2.0,JTA1.2,JPA2.1,和Bean Validation1.1.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值