spring框架简介

概述

Spring 是最受欢迎的企业级Java 应用程序开发框架。数以百万的来自世界各地的开发人员使用 Spring 框架来创建好性能、易于测试、可重用的代码。

Spring 框架是一个开源的Java 平台,它最初是由 Rod Johnson 编写的,并且 2003 年 6 月首次在Apache 2.0 许可下发布。

当谈论到大小和透明度时, Spring 是轻量级的。 Spring 框架的基础版本是在 2 MB 左右的。

Spring 框架的核心特性可以用于开发任何 Java 应用程序,但是在 Java EE 平台上构建 web 应用程序是需要扩展的。 Spring 框架的目标是使 J2EE 开发变得更容易使用,通过启用基于 POJO 编程模型来促进良好的编程实践。

体系结构

Spring 有可能成为所有企业应用程序的一站式服务点,然而,Spring是模块化的,允许你挑选和选择适用于你的模块,不必要把剩余部分也引入。下面的部分对在Spring 框架中所有可用的模块给出了详细的介绍。

Spring 框架提供约20 个模块,可以根据应用程序的要求来使用。

核心容器

核心容器由核心,Bean,上下文和表达式语言模块组成,它们的细节如下:

·        核心模块提供了框架的基本组成部分,包括IoC 和依赖注入功能。

·        Bean 模块提供 BeanFactory,它是一个工厂模式的复杂实现。

·        上下文模块建立在由核心和Bean 模块提供的坚实基础上,它是访问定义和配置的任何对象的媒介。ApplicationContext接口是上下文模块的重点。

·        表达式语言模块在运行时提供了查询和操作一个对象图的强大的表达式语言。

数据访问/集成

数据访问/集成层包括 JDBCORMOXMJMS 和事务处理模块,它们的细节如下:

·        JDBC 模块提供了删除冗余的 JDBC 相关编码的 JDBC 抽象层。

·        ORM 模块为流行的对象关系映射 API,包括 JPAJDOHibernate iBatis,提供了集成层。

·        OXM 模块提供了抽象层,它支持对 JAXBCastorXMLBeansJiBX XStream 的对象/XML 映射实现。

·        Java 消息服务 JMS 模块包含生产和消费的信息的功能。

·        事务模块为实现特殊接口的类及所有的 POJO 支持编程式和声明式事务管理。

Web

Web 层由WebWeb-MVCWeb-Socket Web-Portlet 组成,它们的细节如下:

·        Web 模块提供了基本的面向 web 的集成功能,例如多个文件上传的功能和使用 servlet 监听器和面向 web 应用程序的上下文来初始化 IoC 容器。

·        Web-MVC 模块包含 Spring 的模型-视图-控制器(MVC),实现了web 应用程序。

·        Web-Socket 模块为 WebSocket-based 提供了支持,而且在 web 应用程序中提供了客户端和服务器端之间通信的两种方式。

·        Web-Portlet 模块提供了在 portlet 环境中实现 MVC,并且反映了 Web-Servlet 模块的功能。

其他

还有其他一些重要的模块,像AOPAspectsInstrumentationWeb 和测试模块,它们的细节如下:

·        AOP 模块提供了面向方面的编程实现,允许你定义方法拦截器和切入点对代码进行干净地解耦,它实现了应该分离的功能。

·        Aspects 模块提供了与 AspectJ 的集成,这是一个功能强大且成熟的面向切面编程(AOP)框架。

·        Instrumentation 模块在一定的应用服务器中提供了类 instrumentation 的支持和类加载器的实现。

·        Messaging 模块为 STOMP 提供了支持作为在应用程序中 WebSocket 子协议的使用。它也支持一个注解编程模型,它是为了选路和处理来自WebSocket 客户端的 STOMP 信息。

·        测试模块支持对具有 JUnit TestNG 框架的 Spring 组件的测试。

Spring 框架和通用日志安装目录所需的核心 JAR 文件:

·        commons-logging-1.1.1

·        spring-aop-4.1.6.RELEASE

·        spring-aspects-4.1.6.RELEASE

·        spring-beans-4.1.6.RELEASE

·        spring-context-4.1.6.RELEASE

·        spring-context-support-4.1.6.RELEASE

·        spring-core-4.1.6.RELEASE

·        spring-expression-4.1.6.RELEASE

·        spring-instrument-4.1.6.RELEASE

·        spring-instrument-tomcat-4.1.6.RELEASE

·        spring-jdbc-4.1.6.RELEASE

·        spring-jms-4.1.6.RELEASE

·        spring-messaging-4.1.6.RELEASE

·        spring-orm-4.1.6.RELEASE

·        spring-oxm-4.1.6.RELEASE

·        spring-test-4.1.6.RELEASE

·        spring-tx-4.1.6.RELEASE

·        spring-web-4.1.6.RELEASE

·        spring-webmvc-4.1.6.RELEASE

·        spring-webmvc-portlet-4.1.6.RELEASE

·        spring-websocket-4.1.6.RELEASE

Spring IoC 容器

IoC 容器

Spring 容器是Spring 框架的核心。容器将创建对象,把它们连接在一起,配置它们,并管理他们的整个生命周期从创建到销毁。Spring容器使用依赖注入(DI)来管理组成一个应用程序的组件。这些对象被称为Spring Beans

通过阅读配置元数据提供的指令,容器知道对哪些对象进行实例化,配置和组装。配置元数据可以通过XMLJava 注释或 Java 代码来表示。下图是 Spring 如何工作的高级视图。 Spring IoC 容器利用 Java POJO 类和配置元数据来生成完全配置和可执行的系统或应用程序。

Spring 提供了以下两种不同类型的容器。

序号

容器 & 描述

1

Spring BeanFactory 容器

它是最简单的容器,给 DI 提供了基本的支持,它用org.springframework.beans.factory.BeanFactory 接口来定义。

BeanFactory 或者相关的接口,如 BeanFactoryAwareInitializingBeanDisposableBean

Spring 中仍然存在具有大量的与 Spring 整合的第三方框架的反向兼容性的目的。

2

Spring ApplicationContext 容器

该容器添加了更多的企业特定的功能,例如从一个属性文件中解析文本信息的能力,

发布应用程序事件给感兴趣的事件监听器的能力。该容器是由 org.springframework.context.ApplicationContext 接口定义。

ApplicationContext 容器包括 BeanFactory 容器的所有功能,所以通常建议使用ApplicationContext 。BeanFactory 仍然可以用于轻量级的应用程序,如移动设备或基于 applet 的应用程序,其中它的数据量和速度是显著。

Sping 的 BeanFactory 容器

这是一个最简单的容器,它主要的功能是为依赖注入DI提供支持,这个容器接口在org.springframework.beans.factory.BeanFactor 中被定义。BeanFactory 和相关的接口,比如,BeanFactoryAware DisposableBeanInitializingBean,仍旧保留在 Spring 中,主要目的是向后兼容已经存在的和那些 Spring 整合在一起的第三方框架。

Spring 中,有大量对 BeanFactory 接口的实现。其中,最常被使用的是 XmlBeanFactory 类。这个容器从一个 XML 文件中读取配置元数据,由这些元数据来生成一个被配置化的系统或者应用。

在资源宝贵的移动设备或者基于applet 的应用当中,BeanFactory 会被优先选择。否则,一般使用的是ApplicationContext,除非你有更好的理由选择BeanFactory

Spring ApplicationContext 容器

Application Context spring 中较高级的容器。和 BeanFactory 类似,它可以加载配置文件中定义的 bean,将所有的 bean 集中在一起,当有请求的时候分配 bean另外,它增加了企业所需要的功能,比如,从属性文件从解析文本信息和将事件传递给所指定的监听器。这个容器在org.springframework.context.ApplicationContext interface 接口中定义。

ApplicationContext 包含 BeanFactory 所有的功能,一般情况下,相对于 BeanFactoryApplicationContext 会被推荐使用。BeanFactory 仍然可以在轻量级应用中使用,比如移动设备或者基于 applet 的应用程序。

最常被使用的ApplicationContext 接口实现:

·        FileSystemXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你需要提供给构造器 XML 文件的完整路径

·        ClassPathXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你不需要提供 XML 文件的完整路径,只需正确配置 CLASSPATH 环境变量即可,因为,容器会从 CLASSPATH 中搜索 bean 配置文件。

·        WebXmlApplicationContext:该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean

Bean 定义

被称作 bean 的对象是构成应用程序的支柱也是由 Spring IoC 容器管理的。bean 是一个被实例化,组装,并通过 Spring IoC 容器所管理的对象。这些 bean 是由用容器提供的配置元数据创建的

bean 定义包含称为配置元数据的信息,下述容器也需要知道配置元数据:

·        如何创建一个bean

·        bean 的生命周期的详细信息

·        bean 的依赖关系

上述所有的配置元数据转换成一组构成每个bean 定义的下列属性。

属性

描述

class

这个属性是强制性的,并且指定用来创建 bean bean 类。

name

这个属性指定唯一的 bean 标识符。在基于 XML 的配置元数据中,你可以使用 ID / name 属性来指定 bean 标识符。

scope

这个属性指定由特定的 bean 定义创建的对象的作用域

constructor-arg

它是用来注入依赖关系的。

properties

它是用来注入依赖关系的。

autowiring mode

它是用来注入依赖关系的。

lazy-initialization mode

延迟初始化的 bean 告诉 IoC 容器在它第一次被请求时,而不是在启动时去创建一个 bean 实例。

initialization 方法

bean 的所有必需的属性被容器设置之后,调用回调方法

destruction 方法

当包含该 bean 的容器被销毁时,使用回调方法

Spring 配置元数据

Spring IoC 容器完全由实际编写的配置元数据的格式解耦。有下面三个重要的方法把配置元数据提供给Spring 容器:

·        基于 XML 的配置文件。

·        基于注解的配置

·        基于 Java 的配置

你已经看到了如何把基于 XML 的配置元数据提供给容器,但是让我们看看另一个基于 XML 配置文件的例子,这个配置文件中有不同的 bean 定义,包括延迟初始化,初始化方法和销毁方法的:

<?xml version="1.0"encoding="UTF-8"?>

<beansxmlns="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-3.0.xsd">

  <!-- A simple bean definition -->

  <bean id="..." class="...">

      <!-- collaborators and configuration for this bean go here -->

  </bean>

  <!-- A bean definition with lazy init set on -->

  <bean id="..." class="..."lazy-init="true">

      <!-- collaborators and configuration for this bean go here -->

  </bean>

  <!-- A bean definition with initialization method -->

  <bean id="..." class="..."init-method="...">

      <!-- collaborators and configuration for this bean go here -->

  </bean>

  <!-- A bean definition with destruction method -->

  <bean id="..." class="..."destroy-method="...">

      <!-- collaborators and configuration for this bean go here -->

  </bean>

  <!-- more bean definitions go here -->

</beans>

 

Bean 的作用域

当在 Spring 中定义一个 bean 时,你必须声明该 bean 的作用域的选项。例如,为了强制 Spring 在每次需要时都产生一个新的 bean 实例,你应该声明 bean 的作用域的属性为 prototype。同理,如果你想让 Spring 在每次需要时都返回同一个bean实例,你应该声明 bean 的作用域的属性为 singleton

Spring 框架支持以下五个作用域,如果你使用web-aware ApplicationContext 时,其中三个是可用的。

作用域

描述

singleton

该作用域将 bean 的定义的限制在每一个 Spring IoC 容器中的一个单一实例(默认)

prototype

该作用域将单一 bean 的定义限制在任意数量的对象实例。

request

该作用域将 bean 的定义限制为 HTTP 请求。只在 web-aware Spring ApplicationContext 的上下文中有效。

session

该作用域将 bean 的定义限制为 HTTP 会话。只在web-aware Spring ApplicationContext的上下文中有效。

global-session

该作用域将 bean 的定义限制为全局 HTTP 会话。只在 web-aware Spring ApplicationContext 的上下文中有效。

Bean 的生命周期

理解 Springbean 的生命周期很容易。当一个 bean 被实例化时,它可能需要执行一些初始化使它转换成可用状态。同样,当 bean 不再需要,并且从容器中移除时,可能需要做一些清除工作。

尽管还有一些在 Bean 实例化和销毁之间发生的活动,但是本章将只讨论两个重要的生命周期回调方法,它们在bean 的初始化和销毁的时候是必需的。

为了定义安装和拆卸一个 bean,我们只要声明带有 init-method / destroy-method 参数的init-method属性指定一个方法,在实例化 bean 时,立即调用该方法。同样,destroy-method 指定一个方法,只有从容器中移除 bean 之后,才能调用该方法。

初始化回调

org.springframework.beans.factory.InitializingBean 接口指定一个单一的方法:

void afterPropertiesSet() throws Exception;

因此,你可以简单地实现上述接口和初始化工作可以在afterPropertiesSet() 方法中执行,如下所示:

public class ExampleBean implements InitializingBean {
   
    public void afterPropertiesSet() {  
        // do some initialization work

   }

}

在基于 XML 的配置元数据的情况下,你可以使用 init-method 属性来指定带有 void 无参数方法的名称。例如:

<bean id="exampleBean" class="examples.ExampleBean" init-method="init"/>

下面是类的定义:

public class ExampleBean {
   
    public void init() { 
        // do some initialization work

   }

}

销毁回调

org.springframework.beans.factory.DisposableBean 接口指定一个单一的方法:

void destroy() throws Exception;

因此,你可以简单地实现上述接口并且结束工作可以在destroy() 方法中执行,如下所示:

public class ExampleBean implements DisposableBean {
   
    public void destroy() {

        // do some destruction work

   }

}

在基于 XML 的配置元数据的情况下,你可以使用 destroy-method 属性来指定带有 void 无参数方法的名称。例如:

<bean id="exampleBean" class="examples.ExampleBean" destroy-method="destroy"/>

下面是类的定义:

public class ExampleBean {
   
    public void destroy() {    
        // do some destruction work

   }

}

如果你在非 web 应用程序环境中使用 Spring IoC 容器;例如在丰富的客户端桌面环境中;那么在 JVM 中你要注册关闭 hook。这样做可以确保正常关闭,为了让所有的资源都被释放,可以在单个 beans 上调用 destroy 方法。

Spring——Bean 后置处理器

BeanPostProcessor 接口定义回调方法,你可以实现该方法来提供自己的实例化逻辑,依赖解析逻辑等。你也可以在Spring 容器通过插入一个或多个BeanPostProcessor 的实现来完成实例化,配置和初始化一个bean之后实现一些自定义逻辑回调方法。

你可以配置多个 BeanPostProcesso r接口,通过设置 BeanPostProcessor 实现的 Ordered 接口提供的 order 属性来控制这些 BeanPostProcessor 接口的执行顺序。

BeanPostProcessor 可以对 bean(或对象)实例进行操作,这意味着 Spring IoC 容器实例化一个 bean 实例,然后 BeanPostProcessor 接口进行它们的工作。

ApplicationContext 会自动检测由 BeanPostProcessor 接口的实现定义的 bean,注册这些 bean 为后置处理器,然后通过在容器中创建 bean,在适当的时候调用它。

Bean 定义继承

bean 定义可以包含很多的配置信息,包括构造函数的参数,属性值,容器的具体信息例如初始化方法,静态工厂方法名,等等。

bean 的定义继承父定义的配置数据。子定义可以根据需要重写一些值,或者添加其他值。

Spring Bean 定义的继承与Java 类的继承无关,但是继承的概念是一样的。你可以定义一个父bean 的定义作为模板和其他子 bean 就可以从父 bean 中继承所需的配置。

当你使用基于 XML 的配置元数据时,通过使用父属性,指定父 bean 作为该属性的值来表明子 bean 的定义。

例如:

下面是配置文件 Beans.xml,在该配置文件中我们定义有两个属性 message1  message2  “helloWorld” bean。然后,使用 parent 属性把 “helloIndia” bean 定义为 “helloWorld” bean 的孩子。这个子 bean 继承 message2 的属性,重写 message1 的属性,并且引入一个属性 message3

<?xml version="1.0" encoding="UTF-8"?>

<beansxmlns="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-3.0.xsd">

   <beanid="helloWorld" class="com.tutorialspoint.HelloWorld">

      <property name="message1"value="Hello World!"/>

      <property name="message2" value="Hello Second World!"/>

   </bean>

   <bean id="helloIndia" class="com.tutorialspoint.HelloIndia" parent="helloWorld">

      <propertyname="message1" value="Hello India!"/>

      <propertyname="message3" value="Namaste India!"/>

   </bean>

</beans>

 

这里是 HelloWorld.java 文件的内容:

package com.tutorialspoint;

public class HelloWorld
 {  
private String message1;
private String message2;

   
public void setMessage1(String message)
{

 this.message1  = message;

   }

   
public void setMessage2(String message)
{

this.message2  = message;

   }

   
public void getMessage1()
{

    System.out.println("World Message1 : "+ message1);

 }

   
public void getMessage2()
{

    System.out.println("World Message2 : " + message2);

 }

}

这里是 HelloIndia.java 文件的内容:

package com.tutorialspoint;

 

public class HelloIndia {

   private String message1;

   private String message2;

   private String message3;

 

   public void setMessage1(String message){

      this.message1  = message;

   }

 

   public void setMessage2(String message){

      this.message2  = message;

   }

 

   public void setMessage3(String message){

      this.message3  = message;

   }

 

   public void getMessage1(){

     System.out.println("India Message1 : " + message1);

   }

 

   public void getMessage2(){

     System.out.println("India Message2 : " + message2);

   }

 

   public void getMessage3(){

     System.out.println("India Message3 : " + message3);

   }

}

下面是 MainApp.java 文件的内容:

package com.tutorialspoint;

 

import org.springframework.context.ApplicationContext;

importorg.springframework.context.support.ClassPathXmlApplicationContext;

 

public class MainApp {

   public static void main(String[]args) {

      ApplicationContextcontext = new ClassPathXmlApplicationContext("Beans.xml");

      HelloWorld objA =(HelloWorld) context.getBean("helloWorld");

      objA.getMessage1();

      objA.getMessage2();

      HelloIndia objB =(HelloIndia) context.getBean("helloIndia");

      objB.getMessage1();

      objB.getMessage2();

      objB.getMessage3();

   }

}

Spring 依赖注入

依赖注入

每个基于应用程序的 java 都有几个对象,这些对象一起工作来呈现出终端用户所看到的工作的应用程序。当编写一个复杂的Java 应用程序时,应用程序类应该尽可能独立于其他 Java 类来增加这些类重用的可能性,并且在做单元测试时,测试独立于其他类的独立性。依赖注入(或有时称为布线)有助于把这些类粘合在一起,同时保持他们独立。

假设你有一个包含文本编辑器组件的应用程序,并且你想要提供拼写检查。标准代码看起来是这样的:

publicclassTextEditor {

   
    private SpellChecker spellChecker;  

   
    public TextEditor() {

    spellChecker = new SpellChecker();

  }

}

在这里我们所做的就是创建一个TextEditor SpellChecker 之间的依赖关系。在控制反转的场景中,我们反而会做这样的事情:

public class TextEditor {

    private SpellChecker spellChecker;
 
    public TextEditor(SpellChecker spellChecker) {
        this.spellChecker = spellChecker;
   }

}

在这里,TextEditor不应该担心 SpellChecker 的实现。SpellChecker 将会独立实现,并且在 TextEditor 实例化的时候将提供给 TextEditor,整个过程是由 Spring 框架的控制。

在这里,我们已经从 TextEditor 中删除了全面控制,并且把它保存到其他地方(即 XML 配置文件),且依赖关系(即 SpellChecker 类)通过类构造函数被注入到TextEditor 类中。因此,控制流通过依赖注入(DI)已经反转,因为你已经有效地委托依赖关系到一些外部系统。

依赖注入的第二种方法是通过 TextEditor 类的 Setter 方法,我们将创建 SpellChecker 实例,该实例将被用于调用 setter 方法来初始化 TextEditor 的属性。

因此,DI 主要有两种变体和下面的两个子章将结合实例涵盖它们:

序号

依赖注入类型 & 描述

1

Constructor-based dependency injection

当容器调用带有多个参数的构造函数类时,实现基于构造函数的 DI,每个代表在其他类中的一个依赖关系。

2

Setter-based dependency injection

基于 setter 方法的 DI 是通过在调用无参数的构造函数或无参数的静态工厂方法实例化 bean 之后容器调用 beans 的 setter 方法来实现的。

你可以混合这两种方法,基于构造函数和基于setter 方法的 DI,然而使用有强制性依存关系的构造函数和有可选依赖关系的 setter是一个好的做法。

代码是 DI 原理的清洗机,当对象与它们的依赖关系被提供时,解耦效果更明显。对象不查找它的依赖关系,也不知道依赖关系的位置或类,而这一切都由Spring 框架控制的。

Spring 框架的 AOP

Spring 框架的 AOP

Spring 框架的一个关键组件是面向方面的编程(AOP)框架。面向方面的编程需要把程序逻辑分解成不同的部分称为所谓的关注点。跨一个应用程序的多个点的功能被称为横切关注点,这些横切关注点在概念上独立于应用程序的业务逻辑。有各种各样的常见的很好的方面的例子,如日志记录、审计、声明式事务、安全性和缓存等。

OOP 中,关键单元模块度是类,而在 AOP 中单元模块度是方面。依赖注入帮助你对应用程序对象相互解耦和 AOP 可以帮助你从它们所影响的对象中对横切关注点解耦。AOP 是像编程语言的触发物,如 Perl.NETJava 或者其他。

Spring AOP 模块提供拦截器来拦截一个应用程序,例如,当执行一个方法时,你可以在方法执行之前或之后添加额外的功能。

AOP 术语

在我们开始使用 AOP 工作之前,让我们熟悉一下 AOP 概念和术语。这些术语并不特定于 Spring,而是与 AOP 有关的。

描述

Aspect

一个模块具有一组提供横切需求的 APIs。例如,一个日志模块为了记录日志将被 AOP 方面调用。应用程序可以拥有任意数量的方面,这取决于需求。

Join point

在你的应用程序中它代表一个点,你可以在插件 AOP 方面。你也能说,它是在实际的应用程序中,其中一个操作将使用 Spring AOP 框架。

Advice

这是实际行动之前或之后执行的方法。这是在程序执行期间通过 Spring AOP 框架实际被调用的代码。

Pointcut

这是一组一个或多个连接点,通知应该被执行。你可以使用表达式或模式指定切入点正如我们将在 AOP 的例子中看到的。

Introduction

引用允许你添加新方法或属性到现有的类中。

Target object

被一个或者多个方面所通知的对象,这个对象永远是一个被代理对象。也称为被通知对象。

Weaving

Weaving 把方面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时,类加载时和运行时完成。

通知的类型

Spring 方面可以使用下面提到的五种通知工作:

通知

描述

前置通知

在一个方法执行之前,执行通知。

后置通知

在一个方法执行之后,不考虑其结果,执行通知。

返回后通知

在一个方法执行之后,只有在方法成功完成时,才能执行通知。

抛出异常后通知

在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。

环绕通知

在建议方法调用之前和之后,执行通知。

实现自定义方面

Spring 支持 @AspectJ annotationstyle 的方法和基于模式的方法来实现自定义方面。这两种方法已经在下面两个子节进行了详细解释。

方法

描述

XML Schema based

方面是使用常规类以及基于配置的 XML 来实现的。

@AspectJ based

@AspectJ 引用一种声明方面的风格作为带有 Java 5 注释的常规 Java 类注释。

Spring JDBC 框架

JDBC 框架概述

在使用普通的 JDBC 数据库时,就会很麻烦的写不必要的代码来处理异常,打开和关闭数据库连接等。但Spring JDBC 框架负责所有的低层细节,从开始打开连接,准备和执行SQL 语句,处理异常,处理事务,到最后关闭连接。

所以当从数据库中获取数据时,你所做的是定义连接参数,指定要执行的SQL 语句,每次迭代完成所需的工作。

SpringJDBC 提供几种方法和数据库中相应的不同的类与接口。我将给出使用 JdbcTemplate 类框架的经典和最受欢迎的方法。这是管理所有数据库通信和异常处理的中央框架类。

JdbcTemplate 类

JdbcTemplate 类执行SQL 查询、更新语句和存储过程调用,执行迭代结果集和提取返回参数值。它也捕获JDBC 异常并转换它们到 org.springframework.dao包中定义的通用类、更多的信息、异常层次结构。

JdbcTemplate 类的实例是线程安全配置的。所以你可以配置JdbcTemplate 的单个实例,然后将这个共享的引用安全地注入到多个DAOs 中。

使用JdbcTemplate 类时常见的做法是在你的 Spring 配置文件中配置数据源,然后共享数据源 bean 依赖注入到 DAO 类中,并在数据源的设值函数中创建了 JdbcTemplate

配置数据源

我们需要提供一个数据源到JdbcTemplate 中,所以它可以配置本身来获得数据库访问。你可以在XML 文件中配置数据源,其中一段代码如下所示:

<bean id="dataSource"

class="org.springframework.jdbc.datasource.DriverManagerDataSource">

   
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>

   
<property name="url" value="jdbc:mysql://localhost:3306/TEST"/>

   
<property name="username" value="root"/>

   
<property name="password" value="password"/>

</bean>

数据访问对象(DAO)

DAO 代表常用的数据库交互的数据访问对象。DAOs提供一种方法来读取数据并将数据写入到数据库中,它们应该通过一个接口显示此功能,应用程序的其余部分将访问它们。

Spring 中,数据访问对象(DAO)支持很容易用统一的方法使用数据访问技术,如 JDBCHibernateJPA 或者 JDO

执行 SQL 语句

我们看看如何使用 SQL jdbcTemplate 对象在数据库表中执行 CRUD(创建、读取、更新和删除)操作。

查询一个整数类型:

String SQL = "select count(*) from Student;

int rowCount = jdbcTemplateObject.queryForInt(SQL);

Spring 事务管理

事务管理

一个数据库事务是一个被视为单一的工作单元的操作序列。这些操作应该要么完整地执行,要么完全不执行。事务管理是一个重要组成部分,RDBMS面向企业应用程序,以确保数据完整性和一致性。事务的概念可以描述为具有以下四个关键属性说成是 ACID

·        原子性:事务应该当作一个单独单元的操作,这意味着整个序列操作要么是成功,要么是失败的。

·        一致性:这表示数据库的引用完整性的一致性,表中唯一的主键等。

·        隔离性:可能同时处理很多有相同的数据集的事务,每个事务应该与其他事务隔离,以防止数据损坏。

·        持久性:一个事务一旦完成全部操作后,这个事务的结果必须是永久性的,不能因系统故障而从数据库中删除。

一个真正的 RDBMS 数据库系统将为每个事务保证所有的四个属性。使用 SQL 发布到数据库中的事务的简单视图如下:

·        使用 begintransaction 命令开始事务。

·        使用 SQL 查询语句执行各种删除、更新或插入操作。

·        如果所有的操作都成功,则执行提交操作,否则回滚所有操作。

Spring 框架在不同的底层事务管理APIs 的顶部提供了一个抽象层。Spring 的事务支持旨在通过添加事务能力到 POJOs 来提供给 EJB 事务一个选择方案。Spring 支持编程式和声明式事务管理。EJBs 需要一个应用程序服务器,但 Spring 事务管理可以在不需要应用程序服务器的情况下实现。

局部事物 vs. 全局事务

局部事务是特定于一个单一的事务资源,如一个JDBC 连接,而全局事务可以跨多个事务资源事务,如在一个分布式系统中的事务。

局部事务管理在一个集中的计算环境中是有用的,该计算环境中应用程序组件和资源位于一个单位点,而事务管理只涉及到一个运行在一个单一机器中的本地数据管理器。局部事务更容易实现。

全局事务管理需要在分布式计算环境中,所有的资源都分布在多个系统中。在这种情况下事务管理需要同时在局部和全局范围内进行。分布式或全局事务跨多个系统执行,它的执行需要全局事务管理系统和所有相关系统的局部数据管理人员之间的协调。

编程式 vs. 声明式

Spring 支持两种类型的事务管理:

·        编程式事务管理:这意味着你在编程的帮助下有管理事务。这给了你极大的灵活性,但却很难维护。

·        声明式事务管理:这意味着你从业务代码中分离事务管理。你仅仅使用注释或 XML 配置来管理事务。

声明式事务管理比编程式事务管理更可取,尽管它不如编程式事务管理灵活,但它允许你通过代码控制事务。但作为一种横切关注点,声明式事务管理可以使用AOP 方法进行模块化。Spring 支持使用 Spring AOP 框架的声明式事务管理。

Spring 事务抽象

Spring 事务抽象的关键是由org.springframework.transaction.PlatformTransactionManager 接口定义,如下所示:

public interface PlatformTransactionManager
{

   
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

   
void commit(TransactionStatus status) throws TransactionException;
   
void rollback(TransactionStatus status) throws TransactionException;

}

序号

方法 & 描述

1

TransactionStatus getTransaction(TransactionDefinition definition)

根据指定的传播行为,该方法返回当前活动事务或创建一个新的事务。

2

void commit(TransactionStatus status)

该方法提交给定的事务和关于它的状态。

3

void rollback(TransactionStatus status)

该方法执行一个给定事务的回滚。

TransactionDefinition 是在 Spring 中事务支持的核心接口,它的定义如下:

public interface TransactionDefinition
{

   
int getPropagationBehavior();

   
int getIsolationLevel();

   
String getName();

   
int getTimeout();

   
boolean isReadOnly();

}

序号

方法 & 描述

1

int getPropagationBehavior()

该方法返回传播行为。Spring 提供了与 EJB CMT 类似的所有的事务传播选项。

2

int getIsolationLevel()

该方法返回该事务独立于其他事务的工作的程度。

3

String getName()

该方法返回该事务的名称。

4

int getTimeout()

该方法返回以秒为单位的时间间隔,事务必须在该时间间隔内完成。

5

boolean isReadOnly()

该方法返回该事务是否是只读的。

下面是隔离级别的可能值:

序号

隔离 & 描述

1

TransactionDefinition.ISOLATION_DEFAULT

这是默认的隔离级别。

2

TransactionDefinition.ISOLATION_READ_COMMITTED

表明能够阻止误读;可以发生不可重复读和虚读。

3

TransactionDefinition.ISOLATION_READ_UNCOMMITTED

表明可以发生误读、不可重复读和虚读。

4

TransactionDefinition.ISOLATION_REPEATABLE_READ

表明能够阻止误读和不可重复读;可以发生虚读。

5

TransactionDefinition.ISOLATION_SERIALIZABLE

表明能够阻止误读、不可重复读和虚读。

下面是传播类型的可能值:

序号

传播 & 描述

1

TransactionDefinition.PROPAGATION_MANDATORY

支持当前事务;如果不存在当前事务,则抛出一个异常。

2

TransactionDefinition.PROPAGATION_NESTED

如果存在当前事务,则在一个嵌套的事务中执行。

3

TransactionDefinition.PROPAGATION_NEVER

不支持当前事务;如果存在当前事务,则抛出一个异常。

4

TransactionDefinition.PROPAGATION_NOT_SUPPORTED

不支持当前事务;而总是执行非事务性。

5

TransactionDefinition.PROPAGATION_REQUIRED

支持当前事务;如果不存在事务,则创建一个新的事务。

6

TransactionDefinition.PROPAGATION_REQUIRES_NEW

创建一个新事务,如果存在一个事务,则把当前事务挂起。

7

TransactionDefinition.PROPAGATION_SUPPORTS

支持当前事务;如果不存在,则执行非事务性。

8

TransactionDefinition.TIMEOUT_DEFAULT

使用默认超时的底层事务系统,或者如果不支持超时则没有。

TransactionStatus 接口为事务代码提供了一个简单的方法来控制事务的执行和查询事务状态。

public interface TransactionStatusextendsSavepointManager
{

   
boolean isNewTransaction();

   
boolean hasSavepoint();

   
void setRollbackOnly();

   
boolean isRollbackOnly();

   
boolean isCompleted();

}

序号

方法 & 描述

1

boolean hasSavepoint()

该方法返回该事务内部是否有一个保存点,也就是说,基于一个保存点已经创建了嵌套事务。

2

boolean isCompleted()

该方法返回该事务是否完成,也就是说,它是否已经提交或回滚。

3

boolean isNewTransaction()

在当前事务时新的情况下,该方法返回 true

4

boolean isRollbackOnly()

该方法返回该事务是否已标记为 rollback-only

5

void setRollbackOnly()

该方法设置该事务为 rollback-only 标记。

Spring 基于注解的配置

Spring 2.5 开始就可以使用注解来配置依赖注入。而不是采用XML 来描述一个 bean 连线,你可以使用相关类,方法或字段声明的注解,将 bean 配置移动到组件类本身。

XML 注入之前进行注解注入,因此后者的配置将通过两种方式的属性连线被前者重写。

注解连线在默认情况下在 Spring 容器中不打开。因此,在可以使用基于注解的连线之前,我们将需要在我们的 Spring 配置文件中启用它。所以如果你想在 Spring 应用程序中使用的任何注解,可以考虑到下面的配置文件。

<?xml version="1.0" encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 
   
<context:annotation-config/>
   
<!-- bean definitions go here -->

</beans>

一旦被配置后,你就可以开始注解你的代码,表明 Spring 应该自动连接值到属性,方法和构造函数。让我们来看看几个重要的注解,并且了解它们是如何工作的:

序号

注解 & 描述

1

@Required

@Required 注解应用于 bean 属性的 setter 方法。

2

@Autowired

@Autowired 注解可以应用到 bean 属性的 setter 方法,非 setter 方法,构造函数和属性。

3

@Qualifier

通过指定确切的将被连线的 bean@Autowired @Qualifier 注解可以用来删除混乱。

4

JSR-250 Annotations

Spring 支持 JSR-250 的基础的注解,其中包括了 @Resource@PostConstruct @PreDestroy 注解。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值