Spring

目录

一、Spring框架介绍

二、Spring框架提供的服务

1、IOC服务(控制反转服务) 

2、DI服务(依赖注入服务)

3、AOP服务(面向切面编程服务)

三、IOC服务

(一)、开发环境搭建

1、pom文件中引入 spring-context jar包

2、创建spring核心配置文件,并且设置需要spring容器帮忙创建的实体类。

3、获取  ApplicationContext接口的实现类 

 4、获取实体类对象

 (二)、IOC服务获取方式

1、基于XML文件方式获取

2、通过注解的方式 

3、两种索要IOC服务方式对比

四、DI服务

(一)通过XML标签形式

1、给基本类型的属性设置默认值

 2、给引用类型的属性设置默认值

(二)、通过注解的方式

1、使用注解,基本数据类型进行设置默认值

2、 使用注解,引用数据类型进行设置默认值

 3、引用类型:如果一个类有多个IOC服务,创建多个对象,使用DI初始化值,怎么区分?

五、 Spring集成MyBatis

(一)、Spring集成MyBatis框架的开发环境搭建 

1、导入jar包

 六、ApplicationContext接口下两个常见实现类

(一)、ClassXmlApplicationContext: 

 (二)、FileSystemXmlApplicationContext

七、JDK动态代理设计模式:

(一)、介绍

(二)、角色划分

1、目标方法

2、目标类

3、目标对象

4、切面类

5、代理对象

(三)、通知(advice)分类

1、前置通知

2、后置通知 

3、环绕通知

4、异常通知

5、最终通知

(四)、JDK动态代理模式代码实现 

 (五)、JDK代理模式的优缺点

八、 Spring框架之AOP服务

(一)、介绍

(二)、AOP服务环境搭建

(三)、获取AOP服务两种方式

        1.XML的形式

2、注解形式

2.1、注解使用Around

 3、Aspest切面类中,前置、后置、环绕方法等。proceedingjoinpoint 和 joinpoint 的区别

八、DataSourceTransactionManager(spring事务相关)

(一)、事务

1、什么是事务

2、事务管理

3、如何确保两条sql语句生成的备份表能够被同一个事务对象管理?

(二)、spring集成事务使用

1、环境搭建

2、通过注解的形式 

3、通过XML文件配置的形式(建议使用)

九、spring结合servlet

(一)、spring结合sevlet基础使用

(二)、监听器解决,每访问servlet后创建一个spring容器对象问题

 十、spring集成监听器

(一)、环境搭建

1、需要jar包

2、web.xml文件中配置监听器

​编辑 3、servlet中获取spring容器对象

4、spring创建容器对象源码分析


一、Spring框架介绍

       Spring使用java语言开发开源框架, Spring 的主要作用就是为代码“解耦”,降低代码间的耦合度。就是让对象和对象(模 块和模块)之间关系不是使用代码关联,而是通过配置来说明。即在 Spring 中说明对象(模 块)的关系。

         Spring 根据代码的功能特点,使用 Ioc 降低业务对象之间耦合度。IoC 使得主业务在相互 调用过程中,不用再自己维护关系了,即不用再自己创建要使用的对象了。而是由 Spring 容器统一管理,自动“注入”,注入即赋值。 而 AOP 使得系统级服务得到了最大复用,且 不用再由程序员手工将系统级服务“混杂”到主业务逻辑中了,而是由 Spring 容器统一完成 “织入”。

二、Spring框架提供的服务

1、IOC服务(控制反转服务) 

        原来在程序中的创建对象方式,现在有Spring容器对象帮助创建指定类的对象,减少手动创建创建对象;

2、DI服务(依赖注入服务)

        有Spring容器对象帮助开发人员,对指定对象进行【初始化】服务,只有被Spring容器对象创建的对象,才有资格享受【DI】服务

3、AOP服务(面向切面编程服务)

        有Spring容器对象帮助开发人员降低JDK动态代理设计模式的使用难度,由Spring容器对象负责【代理类生成】、【代理对象创建】以及【目标类】、【切面类】的实例对象创建

三、IOC服务

        由Spring容器对象,对指定类对象的创建

(一)、开发环境搭建

1、pom文件中引入 spring-context jar包

2、创建spring核心配置文件,并且设置需要spring容器帮忙创建的实体类。

<bean> id:表示创建实体类对应的key, class:表示需要帮忙创建的实体类

3、获取  ApplicationContext接口的实现类 

 4、获取实体类对象

 

 (二)、IOC服务获取方式

1、基于XML文件方式获取

        将指定创建类的信息,写在xml bean标签中,spring容器会自动读取xml文件中指定类进行创建对象

注意:

  •  Spring容器在创建对象完毕后,就会负责将bean标签指定的类进行创建
  • 一个bean标签spring只会创建一个指定类的对象
  • 通过bean标签让spring创建实体类对象,该实体类必须要有无参构造方法(底层通过反射创建)

面试题:是不是所有类都能被spring容器对象来创建实例化对象,如果不存在请说明?

     答案: 不是 ,有些类就不能让spring容器来创建实例化对象

        以下类就不可以:.

  • servlet相关的实现类,比如HttpServle...,监听器、过滤器等实现类。因为这些类的对象都是由Http服务器来创建。
  • 没有无参构造方法的类或者接口等

2、通过注解的方式 

1、需要给让Spring容器对象创建的实体类上面添加 @Component注解

 2、在Spring核心文件中配置,Spring扫描那些包下,遇到@Component注解就会创建实体类对象。如果不告诉Spring,将会整个项目扫描,耗费性能资源;

 3、测试一下


3、两种索要IOC服务方式对比

1、基于XML文件方式获取

优点:

  •  管理范围非常广,即可以是项目中开发人员开发的类,也可以是来自于jar包中类;
  • 集中化关了,对于后续维护降低难度

缺点:  

  • 随着项目中开发的类的数量增加。, spring核心配置占用空间也会逐渐增加,增加项目的容积,来增加项目运营的成本

2、基于注解方式获取

优点:不会增加spring核心配置文件的容积

缺点:只能创建设定范围内包下的类的对象创建,jar包情况不能创建

四、DI服务

        通过XML标签或者注解的形式通知spring对象为某个对象的指定属性设置指定的初始化值

(一)通过XML标签形式

1、给基本类型的属性设置默认值

实体类

spring核心配置文件配置

 

 测试方法

 

 2、给引用类型的属性设置默认值

实体类

 spring核心配置文件

 测试方法

(二)、通过注解的方式

1、使用注解,基本数据类型进行设置默认值

实体类

 测试类

2、 使用注解,引用数据类型进行设置默认值

 实体类

测试类 

 3、引用类型:如果一个类有多个IOC服务,创建多个对象,使用DI初始化值,怎么区分?

 xml中配置一个类中多个IOC服务,并且使用DI初始化值

实体类 

 测试类

 

 我们发现运行报错,原因:就是spring检测到2个符合的IOC对象,spring不知道使用那个

解决办法:使用 @Qualifier()标签,告诉spring使用那个

 再次测试,发现解决问题了!

五、 Spring集成MyBatis

         Spring集成某一种技术:由Spring容器对象负责为指定技术中【核心对象】和【辅助对象】进行初始化和创建,当开发人员使用该技术的时候,直接从Spring容器中获取【核心对象】降低开发人员使用该技术的难度;

比如:我们要使用JDBC操作数据库,核心对象就是:PreparedStatment,为了得到它我们需要创建Driver对象,connect对象,PreparedStatment对象。

后面上述的创建那么多的辅助对象和核心对象,我们就可以交给Spring容器,进行创建;

理解Spring继承MyBatis框架

        1、mybatis框架作者,不希望Spring直接与mybatis的核心类:SqlSessionFactoryBuilder、SqlSessionFactory,直接接触,因此提供了一个SqlSessionFactoryBean类,spring容器创建SqlSessionFactoryBean类对象后,mybatis自动创建SqlSessionFactoryBuilder、SqlSessionFactory类对象

        2、如果想用mybatis Dao层代理服务,需要创建:SqlSession对象;但是mybatis不希望spring直接创建该类对象,因此提供了MapperScannerConfigure类,spring容器创建MapperScannerConfigure对象后,该类会对SqlSession对象进行创建;

     SqlSessionFactoryBean 和 MapperScannerConfigure类存储在mybaits-spring.jar包中

(一)、Spring集成MyBatis框架的开发环境搭建 

1、导入jar包

依赖jar包:

JDK的jar包: java.sql.Driver接口、java.sql.Connect接口、 java.sql.PreparedStatement接口、 java.sql.ResultSet接口、 java.sql.DriverManager类

mysql-conector-java.jar包(MySql厂商提供的,主要是实现MySql相关的接口):com.mysql.jdbc.Driver类、com.mysql.jdbc.JDBC4Connection类、com.mysql.jdbc.JDBC4PreparedStatement类、com.mysql.jdbc.JDBC4ResultSet类

mybatis的jar包:SqlSessionFactoryBuilder类、SqlSessionFactory类、SqlSession类

mybatis-spring.jar(mybatis提供给spring): SqlSessionFactoryBean 类、MapperScanerConfigure类

spring-context.jar(spring)

2、编写spring 配置文件

创建SqlSessionFactoryBean、MapperScanerConfigure对象以及对应属性赋值

 3、配置mybatis文件

 mybatis中不用配置数据库环境信息以及datasource,后面会在spring中配置

4、 编写dao层代理

dao层接口

 dao层接口对应的sql映射文件

 5、实体类

 6、服务层接口以及实现

服务层接口

 实现类

 7、测试类

 运行

 报错:spring提示解析spring.xml文件时候,创建MapperScannerConfigurer类对象报错,提示没有找到下面的类 "org/springframework/dao/support/DaoSupport"

解决办法:pom文件中少jar包

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.3.18</version>
    </dependency>

添加jar包后再次运行

报错: spring提示创建sqlSessionFactoryBean对象时候提示,dataSource属性必须要有值,dataSource中存放的是数据相关信息;

 解决办法,在spring.xml文件中配置dataSource属性,并且给它附初始值

我们查看SqlSessionFactoryBean的源码,发现需要附一个dataSource类型的对象

 此时我们需要借助一个jar包

    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.2.8</version>
    </dependency>

添加jar包,后在spring.xml文件中配置dataSource对象,并且给SqlSessionFactoryBean配置dataSource属性

创建properties文件,配置数据库信息 

 再次运行,提示没有找到sql映射文件。

 解决办法:pom文件中配置

 配置完成,再次运行,运行成功!

 六、ApplicationContext接口下两个常见实现类

(一)、ClassXmlApplicationContext: 

        由这个类生成的spring容器对象只能在当前, 在当前项目的编译路径下寻找spring核心配置文件

 (二)、FileSystemXmlApplicationContext

        由这个类生成的spring容器对象只能在当前计算机的文件系统中寻找spring核心配置文件

我们将spring配置文件放在E盘,测试一下

运行成功 

七、JDK动态代理设计模式:

(一)、介绍

  SUN公司在jdk.jar提供一组工具类。用来帮助开发人员降低【动态代理设计模式】使用难度,提供一个【代理对象】帮助开发人员得到本次目标类的Class对象帮助开发人员得到本次目标方法Method对象,并自动将这些信息传入到切面对象中invoke方法

(二)、角色划分

1、目标方法

        来自于对应接口中的方法,这些接口需要与新增功能进行关联

2、目标类

        就是对应接口的实现类

3、目标对象

        目标类生成的实例对象

4、切面类

        负责将【新增功能】与目标方法进行关联的一个工具类。在JDK动态代理模式中,要求所有切面类必须实现InvocationHandler接口,用于对切面类中invoke方法进行统一管理;

5、代理对象

        JDK动态代理设计模式,提供一个工具类Proxy。这个工具类负责在内存中生成一个【代理类】,并且负责创建【代理类】的实例对象,这个对象就是【代理对象】。负责帮助开发人员简化切面类中invoke方法调用难度。 代理对象接收到请求信息并将请求信息交给切面对象,切面对象调用目标类的方法

(三)、通知(advice)分类

1、前置通知

        先【新增功能方法】在【目标方法】

2、后置通知 

        先【目标方法】在【新增功能方法】

3、环绕通知

        先【新增功能1】在【目标方法】最后【新增功能2】

4、异常通知

        只有【目标方法】运行抛出异常时,才会进行执行【新功能】

5、最终通知

        先运行目标方法,无论目标方法是否正常执行,都会执行新功能

(四)、JDK动态代理模式代码实现 

目标类接口,目标方法

 目标类(实现目标接口的类)

目标类1

 目标类2

 目标类3

代理对象工程类(生成代理对象)
        传入目标类的反射对象,生成该类的代理服务对象,通过代理对象调用目标方法

 切面类

        负责关联目标方法和新增功能的一个工具类

package com.zxb.aspect;

import com.zxb.sevice.BaseService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Date;

//切面类:解决将【新增功能】与【目标方法】关联起来的工具类
public class MyAspect implements InvocationHandler {
    //目标对象
    private BaseService target;

    public MyAspect(BaseService target) {
        this.target = target;
    }

    //解决问题inovke:BaseService接口下所有服务方法在运行完毕时,输出【结束时间】
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        try{
            /*
            * 前置通知:  前置方法
            */
            //1.目标方法执行
            result = method.invoke(target, args);
            /*
            * 后置通知: 后置方法
            */
            //2.目标方法执行后,调用新增功能
            newFun();
        }catch (Exception e){
            /*
            * 异常通知:  出现异常执行方法
            */
        }finally {
            /*
            * 最终通知 最终执行方法
            */
        }
        return result;
    }

    //新增功能
    private void  newFun(){
        System.out.println("service_1方法运行结束的时间是 "+new Date());
    }
}

测试类

 

 (五)、JDK代理模式的优缺点

    1、优点:通过一个代理对象,操作目标方法,降低了开发人员使用切面对象来解决问题的难度

    2、缺点:代理对象生成步骤过于晦涩难懂,目标方法与新增功能调用顺序过于死板

八、 Spring框架之AOP服务

(一)、介绍

        AOP服务称为【面向切面编程服务】,降低了开发人员使用JDK动态代理模式的使用难度。aop由spring容器对象负责代理对象的生成,为了得到这个服务,开发人员必须将【目标对象】和【切面对象】都交给Spring容器对象来创建

(二)、AOP服务环境搭建

        需要jar包: spring-context.jar、 spring-aspectj.jar

(三)、获取AOP服务两种方式

        1.XML的形式

目标类接口

目标类

 切面类

spring.xml文件 

 测试类 

 

 我们发现执行目标方法service_01时,先执行了前置方法,最后执行了后置方法,service_02未执行;

2、注解形式

目标类接口

 目标类

 切面类

 spring.xml文件

 测试类

我们发现twoService代理服务对象调用目标方法,不走前置和后置方法,因为twoService不满足Aspect切入表达式。

2.1、注解使用Around

切面类

 使用around时候需要注意 方法是否有返回值,因为method.proceed()调用目标方法,目标方法有返回值,这边需要将返回值返回,没有则使用void;

 测试类

 

 3、Aspest切面类中,前置、后置、环绕方法等。proceedingjoinpoint 和 joinpoint 的区别

JoinPoint:提供访问连接点的静态部分,如被通知方法签名、连接点类型等:

 Proceedingjoinpoint 继承了 JoinPoint :是在JoinPoint的基础上暴露出 proceed 这个方法。proceed很重要,这个是aop代理链执行的方法。

        环绕通知 ProceedingJoinPoint 执行proceed方法的作用是让目标方法执行,这也是环绕通知和前置、后置通知方法的一个最大区别。

八、DataSourceTransactionManager(spring事务相关)

(一)、事务

1、什么是事务

        事务(Transaction)。对采用了InnoDB管理的表文件的数据行, 来进行操作时,InnoDB要求MySql服务器必须先对表文件内容进行备份,生成一个备份表,然后才能对表中的数据行进行处理,事务是MySql服务器生成的一个管理对象,专门用来针对本次操作中生成的备份表进行管理。

2、事务管理

       1) commit:  提交;销毁掉本次操作中所有的备份表
       2) rollback:回滚;将本次操作中所有的备份表覆盖到原始表,从而达到恢复数据的目的

3、如何确保两条sql语句生成的备份表能够被同一个事务对象管理?

        只要确保两天sql语句由同一个通道推送到mysql即可。就是使用同一个connection对象;

(二)、spring集成事务使用

        spring容器对象来创建来自于spring-jdbc.jar中; DataSourceTransactionManager类的对象,这个对象将作为切面对象,为指定的service层中方法提供事务管理服务

    1.这个类来自于spring-jdbc.jar
    2.这个类用来充当【切面类】,为项目中指定的service
      方法提供事务管理。
    3.此时借助于Spring容器对象来创建当前类的代理对象。
    4.开发人员从今往后,在service层开发中只需要关注服务
      而不必关心事务管理。

    5.将DataSourceTransactionManager与服务方法关联方式

1、环境搭建

1、需要引入spring-jdbc.jar包

2、spring.xml文件中,配置DataSourceTransactionManager的对象,通知spring创建DataSourceTransactionManager容器对象创建代理对象

2、通过注解的形式 

pom文件引入相关jar包

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

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.zxb</groupId>
  <artifactId>17_XML_DataSourceTransactionManger</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>17_XML_DataSourceTransactionManger</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

    <!-- myBatis相关jar包 -->
    <!-- mysql -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.38</version>
    </dependency>
    <!-- mybatis框架  -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.6</version>
    </dependency>
    <!-- spring 主要提供:IOC,DI,AOP服务 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.3.18</version>
    </dependency>
    <!--  mybatis 提供给spring  -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.6</version>
    </dependency>

  <!--  提供dataSource类  -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.2.8</version>
    </dependency>

    <!--  DataSourceTransactionManager事务类,提供给spring  -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.3.14</version>
    </dependency>

    <!-- AOP切面类   -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.3.18</version>
    </dependency>

  </dependencies>

  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory><!--所在的目录-->
        <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>

    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

 resource文件夹

 jdbc配置文件

mybatis配置文件 spring配置文件

<?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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <context:component-scan base-package="com.zxb.serviceImpl"></context:component-scan>

    <!--  设置dataSource  -->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${driver}"></property>
        <property name="url" value="${jdbc_url}"></property>
        <property name="username" value="${jdbc_userName}"></property>
        <property name="password" value="${jdbc_passWord}"></property>
        <property name="initialSize" value="${initialSize}"></property>
        <property name="maxActive" value="${maxActive}"></property>
    </bean>
    <!--  设置sqlSessionFactoryBean  -->
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="configLocation" value="classpath:mybatis.xml"></property>
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 设置MapperScannerConfigurer   -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"></property>
        <property name="basePackage" value="com.zxb.dao"></property>
    </bean>
    <!--
        要求Spring容器对象来创建来自于spring-jdbc.jar中
        DataSourceTransactionManger的对象,这个对象将作为切面对象
        为指定的service层中方法提供事务管理服务
    -->
    <!--
      要求spring容器对象来创建来自于spring-jdbc.jar中;
      DataSourceTransactionManager的对象,这个对象将作为切面对象,为指定的service层中方法提供事务管理服务
      -->
    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--  通知spring容器对象为DataSourceTransactionManager容器对象创建代理对象  -->
    <tx:annotation-driven transaction-manager="dataSourceTransactionManager"></tx:annotation-driven>
    
</beans>

dao层接口

 

 实体类

 

 service层

 我们只需要给对应方法上面添加@Transactional标签,该方法就是添加事务。

测试类 

1、我们先验证一下回滚的操作,我们将sql映射文件,sql语句写错。

 2、运行测试类方法

        我可以看出,每个sql都是用的同一个sqlsession对象, 我们发现其中一个sql运行报错了,查看数据库。数据显示所有的数据都已经进行回滚了,说明事务起到作用了,失败则rollback;

3、我们修改正确sql语句,运行测试方法

 4、发现数据库数据都已经删除

3、通过XML文件配置的形式(建议使用)

修改spring.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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:component-scan base-package="com.zxb.serviceImpl"></context:component-scan>

    <!--  设置dataSource  -->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${driver}"></property>
        <property name="url" value="${jdbc_url}"></property>
        <property name="username" value="${jdbc_userName}"></property>
        <property name="password" value="${jdbc_passWord}"></property>
        <property name="initialSize" value="${initialSize}"></property>
        <property name="maxActive" value="${maxActive}"></property>
    </bean>
    <!--  设置sqlSessionFactoryBean  -->
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="configLocation" value="classpath:mybatis.xml"></property>
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 设置MapperScannerConfigurer   -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"></property>
        <property name="basePackage" value="com.zxb.dao"></property>
    </bean>


    <!--
        在容器中添加事务管理器:
            要求Spring容器对象来创建来自于spring-jdbc.jar中
            DataSourceTransactionManger的对象,这个对象将作为切面对象
            为指定的service层中方法提供事务管理服务
    -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--
        配置事务通知:
           指定需要与DataSourceTransactionManger
           关联的服务方法名称,(可以是表达式)
    -->
    <tx:advice id="advice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="delete.*"/>
            <tx:method name="add.*"></tx:method>
        </tx:attributes>
    </tx:advice>

    <!--
        配置增强器:
            指定将配置好的事务通知,植入给谁
    -->
    <!--  aop配置: 通知应用的切入点  -->
    <aop:config>
        <aop:pointcut id="servicePt" expression="execution(public * com.zxb.serviceImpl.*(..))"/>
        <!--   声明增强器: 通知和切入点组合     -->
        <aop:advisor advice-ref="advice" pointcut-ref="servicePt"></aop:advisor>
    </aop:config>
</beans>

  从上面配置可以看出,只有 add*和delete*的方法走事务,其他方法不走事务;

注意:不要写add.*、delete.*,如果这样写就是找 add. 、delete.  相关的方法,而不是 add、delet相关方法

dao层接口以及sql映射文件

 

 service接口以及实现

 测试类方法

我们故意将sql映射文件修改错误,执行test01方法

         我们发现给dept表插入sql执行成功,给student表插入sql失败。我们查看数据库,dept和student表都没有插入成功。从而证明addStuDept方法走事务,因此数据回滚了

我们故意将删除deptNo表sql书写错误,我们测试removeDeptNo方法,我们运行test02方法

         我们发现student表中数据删除了,dept表数据没有删除,因此没有走事务,没有产生回滚的作用;

注意:我们平时使用事务,最好使用xml文件配置,这样可以归到那些方法走事务,那些方法不走事务。

九、spring结合servlet

(一)、spring结合sevlet基础使用

项目结构

 controller里面的servlet,其他文件数据和上面spring项目一样

        我们通过spring容器对象创建的对象,功能非常饱满,Dao层的属性已经初始化,并且service也已经关联了事务。        

 我们可以发现我们在每个servlet对应的方法中获取,spring容器对象。假如有多个人访问servlet,每个servlet都创建一个spring容器对象,这样很浪费内存空间。创建spring容器过程中,spring会给对应类创建对象或者创建对应的代理对象;这样也会增加访问servlet的效率;

解决办法,我们可以使用servlet阶段学到的监听器。我们使用监听器对spring容器对象进行创建;

(二)、监听器解决,每访问servlet后创建一个spring容器对象问题

监听器

 我们使用监听器,只要tomcat启动后就会执行的方法,里面写入创建spring容器对象,并且将spring容器对象放到全局作用域中,因此整个项目就只会使用这一个spring容器对象,这样就减少了每次访问servlet创建spring容器对象的问题。我们每次tomcat启动时候,会创建,不存在访问servlet时候创建,访问servlet效率提高,但是启动tomcat时间增加;

servlet中使用spring容器对象

 十、spring集成监听器

        我们上面看到,如果想优化spring容器对象的创建,需要在监听器中写创建spring容器对象的代码;spring也给我们提供了创建监听器,创建spring容器对象的类;

(一)、环境搭建

可以看出我们没有写监听器,我们使用spring给我们创建的监听器,并且给我们把spring容器对象创建好了 

1、需要jar包

2、web.xml文件中配置监听器

 3、servlet中获取spring容器对象

4、spring创建容器对象源码分析

1、spring给我们创建容器对象主要依赖ContextLoaderListener类

ContextLoaderListener类实现了ServletContextListener

 contextInitialized,方法负责创建监听器,并且创建spring容器对象,并且将spring容器对象放到全局作用域中

 在 createWebApplicationContext 方法里面创建

createWebApplicationContext创建完成返回一个WebApplicationContext对象(spring容器对象

 WebApplicationContext 继承的就是ApplicationContext 对象

 我们在看initWebApplicationContext方法中,将获取WebApplicationContext,转换成了ConfigurableWebApplicationContext,正好是ClassPathXmlApplicationContext 和 FileSystemXmlApplicationContext的祖先类,这两个类都能创建spring容器对象

 将spring容器对象设置到servletContext(全局作用域)中

  因此我们获取spring容器对象就要使用 ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE(key)来获取;

 

 

 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值