• 小白学习spring第三天


    第16节:SpringAOP机制详解

    16.1 AOP 概述
    16.1.1 什么是 AOP
    AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
    AOP 动态代理  
    动态代理: 反射 
    反射体现了java语言的动态性。 
    
    • 1
    • 2
    • 3
    • 4
    16.1.2 AOP编程思想
    OOA OOP OOT OOSM 
    AOP 面向切面编程是一种编程思想,是 OOP 的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
    
    • 1
    • 2
    16.1.3 Spring中AOP的常用术语
    Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点
    Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义。 真正被增强了的方法。 transfer方法。 
    Advice(通知/ 增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。 transfer方法,事务相关
    通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。【重点】
    
    Target(目标对象):代理的目标对象: accountService 对象。 
    Proxy (代理):一个类被 AOP 织入增强后,就产生一个结果代理类 Proxy
    Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入
    Aspect(切面):是切入点和通知(引介)的结合
    具体的描述了: 通知应用在具体的某个切点上~ 。 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    16.1.4 AOP 的作用及优势
    作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强
    优势:减少重复代码,提高开发效率,并且便于维护
    
    • 1
    • 2
    16.2 Spring基于XML的AOP配置
     1、搭建maven工程,沿用上一章节转账的业务场景
     2、准备好通知类TransactionManager
     3、讲解基于XML形式的AOP配置,详细介绍每个标签,每个标签当中属性的作用
     4、测试使用AOP进行事务配置
     5、常用通知类型的总结
     6、详解切入点表达式的语法,常用案例的列举
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    16.2.1 构建maven工程添加依赖
    <properties>
            <spring.version>5.2.5.RELEASEspring.version>
    properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>${spring.version}version>
        dependency>
    
        <dependency>
            <groupId>org.aspectjgroupId>
            <artifactId>aspectjweaverartifactId>
            <version>1.8.7version>
        dependency>
    dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    16.2.2 沿用转账业务的代码
    准备实体类,业务层和持久层代码。我们沿用上一章节中的代码即可。
    
    • 1
    16.2.3 创建 Spring 的配置文件并导入约束
    
    <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.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd">
            
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    16.2.4 配置 Spring 的 IOC
    
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        
        <property name="driverClass" value="com.mysql.jdbc.Driver">property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test">property>
        <property name="user" value="root">property>
        <property name="password" value="root">property>
    bean>
    
    
    <bean id="connectionUtils" class="com.offcn.utils.ConnectionUtils">
        
        <property name="dataSource" ref="dataSource">property>
    bean>
    
    
    <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">bean>
    
    
    <bean id="accountDao" class="com.offcn.dao.impl.AccountDaoImpl">
        <property name="queryRunner" ref="queryRunner">property>
        <property name="connectionUtils" ref="connectionUtils">property>
    bean>
    
    
    <bean id="accountService" class="com.offcn.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao">property>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    16.2.5 抽取公共代码制作成通知(advice)
    /**
     * 和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接
     */
    public class TransactionManager {
        private ConnectionUtils connectionUtils;
    
        public void setConnectionUtils(ConnectionUtils connectionUtils) {
            this.connectionUtils = connectionUtils;
        }
        /**
         * 开启事务
         */
        public  void beginTransaction(){
            try {
                connectionUtils.getThreadConnection().setAutoCommit(false);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        /**
         * 提交事务
         */
        public  void commit(){
            try {
                connectionUtils.getThreadConnection().commit();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        /**
         * 回滚事务
         */
        public  void rollback(){
            try {
                connectionUtils.getThreadConnection().rollback();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        /**
         * 释放连接
         */
        public  void release(){
            try {
                connectionUtils.removeConnection();
                connectionUtils.getThreadConnection().close();//还回连接池中
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    16.2.6 通知类用 bean 标签配置
    
    <bean id="txManager" class="com.offcn.utils.TransactionManager">
        <property name="connectionUtils" ref="connectionUtils">property>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    16.2.7 使用 aop:config 声明 AOP 配置
    aop:config: 
       作用: 开始声明aop配置
    <aop:config>
          
    aop:config>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    16.2.8 使用 aop:aspect 配置切面
    aop:aspect
       作用: 用于配置切面
       属性: 
             id :给切面提供一个唯一标识。
             ref:引用配置好的通知类 bean 的 id。
    <aop:aspect id="tdAdvice" ref="txManager">
           
    aop:aspect>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    16.2.9 使用 aop:pointcut 配置切入点表达式
    aop:pointcut
       作用: 用于配置切入点表达式。就是指定对哪些类的哪些方法进行增强。
       属性: expression:用于定义切入点表达式。
             id:用于给切入点表达式提供一个唯一标识
    <aop:pointcut id="point1"
                   expression="execution( public void  com.offcn.service.impl.AccountServiceImpl.transfer(java.lang.String,java.lang.String,java.lang.Double))"/>
            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    16.2.10 使用 aop:xxx 配置对应的通知类型
    aop:before
        作用:用于配置前置通知。指定增强的方法在切入点方法之前执行
        属性:
             method:用于指定通知类中的增强方法名称
    		 ponitcut-ref:用于指定切入点的表达式的引用
    		 poinitcut:用于指定切入点表达式
        执行时间点:
             切入点方法执行之前执行   
    <aop:before method="beginTransaction" pointcut-ref="point1">aop:before>
    aop:after-returning
    	作用: 
        	用于配置后置通知
    	属性:
       		method:指定通知中方法的名称。
      		pointct:定义切入点表达式
       		pointcut-ref:指定切入点表达式的引用
       	执行时间点:
       	    切入点方法正常执行之后。它和异常通知只能有一个执行
       	    
     <aop:after-returning method="commit" pointcut-ref="point1"/> 	    
    aop:after-throwing
    	作用:
    		用于配置异常通知
    	属性:
    		method:指定通知中方法的名称。
    		pointct:定义切入点表达式
    		pointcut-ref:指定切入点表达式的引用
    	执行时间点:
    		切入点方法执行产生异常后执行。它和后置通知只能执行一个
     <aop:after-throwing method="rollback" pointcut-ref="point1"/>	
    aop:after
    	作用:
    		用于配置最终通知
    	属性:
            method:指定通知中方法的名称。
            pointct:定义切入点表达式
            pointcut-ref:指定切入点表达式的引用
    	执行时间点:
    		无论切入点方法执行时是否有异常,它都会在其后面执行。
     
     <aop:after method="release" pointcut-ref="point1"/>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    16.3 切入点表达式说明
    16.3.1 切点表达式的语法
    execution([修饰符] 返回值类型 包名.类名.方法名(参数))
        案例: 
     execution(public void com.offcn.service.impl.AccountServiceImpl.transfer(String,String,Double))
    
    • 1
    • 2
    • 3
    - 访问修饰符可以省略
    - 返回值类型、包名、类名、方法名可以使用星号*  代表任意
    - 包名与类名之间一个点 . 代表当前包下的类,两个点 .. 表示当前包及其子包下的类
    - 参数列表可以使用两个点 .. 表示任意个数,任意类型的参数列表
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    例如:
    
    全匹配方式
    
        public void 
        com.ujiuye.service.impl.AccountServiceImpl.saveAccount(com.ujiuye.domain.Account)
    
    访问修饰符可以省略
    
        void com.ujiuye.service.impl.AccountServiceImpl.saveAccount(com.ujiuye.domain.Account)
    
    返回值可以使用*号,表示任意返回值
    
        * com.ujiuye.service.impl.AccountServiceImpl.saveAccount(com.ujiuye.domain.Account)
    
    包名可以使用 * 号,表示任意包,但是有几级包,需要写几个 *
    
        * *.*.*.*.AccountServiceImpl.saveAccount(com.ujiuye.domain.Account)
    
    使用..来表示当前包,及其子包
    
        * com..AccountServiceImpl.saveAccount(com.ujiuye.domain.Account)
    
    类名可以使用*号,表示任意类
    
        * com..*.saveAccount(com.ujiuye.domain.Account)
    
    方法名可以使用*号,表示任意方法
    
        * com..*.*( com.ujiuye.domain.Account)
    
    参数列表可以使用*,表示参数可以是任意数据类型,但是必须有参数
    
        * com..*.*(*)
    
    参数列表可以使用..表示有无参数均可,有参数可以是任意类型
    
        * com..*.*(..)
    
    全通配方式:
    
        * *..*.*(..) 
    
    注意: 通常情况下,我们都是对业务层的方法进行增强,所以切入点表达式都是切到业务层实现类。
    
        execution(* com.ujiuye.service.impl.*.*(..))
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    16.3.2 环绕通知配置事务管理
    TransactionManager类当中添加方法
    
    • 1
    /**
         * 环绕通知:
         * spring 框架为我们提供了一个接口:ProceedingJoinPoint,它可以作为环绕通知的方法参数。
         * 在环绕通知执行时,spring 框架会为我们提供该接口的实现类对象,我们直接使用就行。
         * @param pjp
         * @return
         */
    public Object transactionAround(ProceedingJoinPoint pjp) {
        //定义返回值
        Object returnValue = null;
        try {
            //获取方法执行所需的参数
            Object[] args = pjp.getArgs();
            //前置通知:开启事务
            beginTransaction();
            //执行方法
            returnValue = pjp.proceed(args);
            //后置通知:提交事务
            commit();
        }catch(Throwable e) {
            //异常通知:回滚事务
            rollback();
            e.printStackTrace();
        }finally {
            //最终通知:释放资源
            release();
        }
        return returnValue;
    }
     aop:around:
    	作用:
    		用于配置环绕通知
    	属性:
            method:指定通知中方法的名称。
            pointct:定义切入点表达式
            pointcut-ref:指定切入点表达式的引用
    	说明:
            它是 spring 框架为我们提供的一种可以在代码中手动控制增强代码什么时候执行的方式。
            注意:通常情况下,环绕通知都是独立使用的
    
    <aop:config>
            <aop:aspect id="tdAdvice" ref="txManager">
                <aop:pointcut id="point1" expression="execution(* com.offcn.service.impl.*.*(..))"/>
                <!-- 配置环绕通知 -->
                <aop:around method="transactionAround" pointcut-ref="point1"/>
            </aop:aspect>
        </aop:config>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    16.4 Spring基于注解的AOP配置
      AOP注解方式和XML方式完成的功能是一样的,只是采用了两种开发方式而已。将原有的XML方式使用注解逐一替代。
    
    • 1
    16.4.1 构建maven工程添加AOP注解的相关依赖
    <properties>
            <spring.version>5.2.5.RELEASE</spring.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
    
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.7</version>
        </dependency>
    </dependencies> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    16.4.2 在配置文件中导入 context 的名称空间且配置
    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:context="http://www.springframework.org/schema/context"
           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
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    16.4.3 资源使用注解配置
    
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        
        <property name="driverClass" value="com.mysql.jdbc.Driver">property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test">property>
        <property name="user" value="root">property>
        <property name="password" value="root">property>
    bean>
    
    
    <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
    bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    16.4.4 在配置文件中指定 spring 要扫描的包
     
     <context:component-scan base-package="com.offcn">context:component-scan>
    
    • 1
    • 2
    16.4.5 通知类使用注解配置
    /**
     * 和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接
     */
    @Component("txManager")
    public class TransactionManager {
        @Autowired
        private ConnectionUtils connectionUtils;
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    16.4.6 在通知类上使用@Aspect 注解声明为切面[重点]
    /**
     * 和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接
     */
    @Component("txManager")
    @Aspect //表明当前类是一个切面类
    public class TransactionManager {
        @Autowired
        private ConnectionUtils connectionUtils;
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    16.4.7 在增强的方法上使用注解配置通知
    @Before
    	作用:
    		把当前方法看成是前置通知
    	属性:
    		value:用于指定切入点表达式,还可以指定切入点表达式的引用。
    		
    //开启事务
    @Before("execution(* com.offcn.service.impl.*.*(..)))")
    public  void beginTransaction(){
        try {
            System.out.println("before..........................");
            connectionUtils.getThreadConnection().setAutoCommit(false);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
     @AfterReturning
    	作用: 
    		把当前方法看成是后置通知。
    	属性: 
    		value:用于指定切入点表达式,还可以指定切入点表达式的引用
    		
    // 提交事务
    @AfterReturning("execution(* com.offcn.service.impl.*.*(..)))")
    public  void commit(){
        try {
            connectionUtils.getThreadConnection().commit();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    @AfterThrowing
    	作用: 
    		把当前方法看成是异常通知。
    	属性: 
    		value:用于指定切入点表达式,还可以指定切入点表达式的引用
    		
    //回滚事务
    @AfterThrowing("execution(* com.offcn.service.impl.*.*(..)))")
    public  void rollback(){
        try {
            connectionUtils.getThreadConnection().rollback();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    @After
    	作用: 
    		把当前方法看成是最终通知。
    	属性: 
    		value:用于指定切入点表达式,还可以指定切入点表达式的引用
    
    //释放连接
    @After("execution(* com.offcn.service.impl.*.*(..)))")
    public  void release(){
        try {
            connectionUtils.removeConnection();
            connectionUtils.getThreadConnection().close();//还回连接池中
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    16.4.8 在 spring 配置文件中开启 spring 对注解 AOP 的支持
    
    <aop:aspectj-autoproxy/>
    
    • 1
    • 2
    16.4.9 环绕通知注解配置
    @Around
    	作用: 
    		把当前方法看成是环绕通知。
    	属性: 
    		value:用于指定切入点表达式,还可以指定切入点表达式的引用。
    // 环绕通知:
    @Around("execution(* com.offcn.service.impl.*.*(..)))")
    public Object transactionAround(ProceedingJoinPoint pjp) {
        //定义返回值
        Object returnValue = null;
        try {
            //获取方法执行所需的参数
            Object[] args = pjp.getArgs();
            //前置通知:开启事务
            beginTransaction();
            //执行方法
            returnValue = pjp.proceed(args);
            //后置通知:提交事务
            commit();
        }catch(Throwable e) {
            //异常通知:回滚事务
            rollback();
            e.printStackTrace();
        }finally {
            //最终通知:释放资源
            release();
        }
        return returnValue;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    16.4.10 切入点表达式注解
    @Pointcut("execution(* com.offcn.service.impl.*.*(..))")
    private void point1() {}
    
    // 环绕通知:
    @Around("point1()")///注意:千万别忘了写括号
    public Object transactionAround(ProceedingJoinPoint pjp) {
        //定义返回值
        Object returnValue = null;
        try {
            //获取方法执行所需的参数
            Object[] args = pjp.getArgs();
            //前置通知:开启事务
            beginTransaction();
            //执行方法
            returnValue = pjp.proceed(args);
            //后置通知:提交事务
            commit();
        }catch(Throwable e) {
            //异常通知:回滚事务
            rollback();
            e.printStackTrace();
        }finally {
            //最终通知:释放资源
            release();
        }
        return returnValue;
    }
    
    总结: 
    (1)applicationContext.xml当中配置的对象, 开启了包扫描器, 注解模式创建。 
    (2TransactionManager : 事务管理器的类: @Aspect注解。 注解在核心配置文件当中。开启一个开关~ 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    16.5 Spring事务详解【掌握】
     1、介绍Spring当中进行事务控制的常用对象以及作用
     2、事务的隔离级别,不同隔离级别产生的错误数据
     3、扩展事务的传播行为,事务传播行为的对应几种情况,面试问题
     4、完成基于XML形式事务配置
    
    • 1
    • 2
    • 3
    • 4
    16.5.1 Spring中事务的API详解
    1. PlatformTransactionManager作用(掌握)
    PlatformTransactionManager 接口是 Spring 的事务管理器,它里面提供了我们常用的操作事务的方法。
    
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    注意:
    
    PlatformTransactionManager 是接口类型,不同的 Dao 层技术则有不同的实现类,例如:Dao 层技术是jdbc 或 mybatis,JdbcTemplate 时:org.springframework.jdbc.datasource.DataSourceTransactionManager .
    
    Dao 层技术是hibernate时:org.springframework.orm.hibernate5.HibernateTransactionManager
    
    
    等价于:  TransactionManager 常用的对象: .DataSourceTransactionManager
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    2. TransactionDefinition作用
    
    TransactionDefinition 是事务的定义信息对象,里面有如下方法
    
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    2.1 事务隔离级别
    
    设置隔离级别,可以解决事务并发产生的问题,如脏读、不可重复读和虚读。
    
    
    • 1
    • 2
    • 3
    • 4
    事务隔离级别说明
    ISOLATION_DEFAULT默认级别,归属下列某一种
    ISOLATION_READ_UNCOMMITTED未提交读,可以读取未提交数据
    ISOLATION_READ_COMMITTED已提交读,只能读取已提交数据,解决脏读问题(Oracle默认级别)
    ISOLATION_REPEATABLE_READ可重复读,解决不可重复度问题(MySQL默认级别)
    ISOLATION_SERIALIZABLE串行化,节约幻读(虚读)问题
    2.2 事务传播行为
    
    • 1
    事务传播行为说明
    REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)
    SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
    MANDATORY使用当前的事务,如果当前没有事务,就抛出异常
    REQUERS_NEW新建事务,如果当前在事务中,把当前事务挂起。
    NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
    NEVER以非事务方式运行,如果当前存在事务,抛出异常
    NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行 REQUIRED 类似的操作
    2.3 事务超时时间
    	默认值是-1,没有超时限制。如果有,以秒为单位进行设置。
    
    • 1
    • 2
    2.4 是否是只读事务
    
    		建议查询时设置为只读。 
    
    		事务只读: 查询操作~  
    
    		写事务:   数据库的写操作。 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    4. TransactionStatus作用
    	TransactionStatus 接口提供的是事务具体的运行状态,方法介绍如下。
    
    • 1
    • 2

    在这里插入图片描述

    5. 三个对象之间的关系:
    	PlatformTransactionManager 会根据 TransactionDefinition 对象当中定义的信息,进行事务的管理操作。 
    	TransactionStatus 记录了事务的状态信息。 
    掌握: PlatformTransactionManager 
    
    • 1
    • 2
    • 3
    • 4
    16.5.2 Spring基于XML的事务配置
    讲解思路: 
     1、准备转账的业务场景,演示没有事务控制时,数据一致性受损
     2、在XML配置文件当中,使用Spring提供的声明式事务进行控制,详解事务控制的每个步骤,每个步骤当中涉及的每个标签,讲解的过程当中复习巩固AOP当中的相关概念,加深学员对概念的理解
     3、测试基于XML声明式事务是否生效
    
    • 1
    • 2
    • 3
    • 4
    (1)添加相关技术依赖
    <properties>
        <spring.version>5.2.5.RELEASEspring.version>
    properties>
    <dependencies>
        
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
            <scope>testscope>
        dependency>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>${spring.version}version>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-testartifactId>
            <version>${spring.version}version>
        dependency>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-jdbcartifactId>
            <version>${spring.version}version>
        dependency>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.47version>
        dependency>
        
        <dependency>
            <groupId>com.mchangegroupId>
            <artifactId>c3p0artifactId>
            <version>0.9.5.2version>
        dependency>
        
        <dependency>
            <groupId>org.aspectjgroupId>
            <artifactId>aspectjweaverartifactId>
            <version>1.8.7version>
        dependency>
    dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    (2)创建配置文件并导入约束
    <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:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
         
        <context:component-scan base-package="com.offcn">context:component-scan>
    
        
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            
            <property name="driverClass" value="com.mysql.jdbc.Driver">property>
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test">property>
            <property name="user" value="root">property>
            <property name="password" value="root">property>
        bean>
        
        
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource">property>
        bean>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    (3)沿用转账业务的代码
    @Repository("accountDao")
    public class AccountDaoImpl implements AccountDao {
    
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        @Override
        public Account findByName(String name) {
            String sql ="select * from account where name =? ";
            Account account =  this.jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Account.class), name);
            return  account;
        }
    
        @Override
        public void update(Account account) {
            String sql ="update account set money =? where name =? ";
            this.jdbcTemplate.update(sql, account.getMoney(), account.getName());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    (4)配置事务管理器
    
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource">property>
    bean>
    
    • 1
    • 2
    • 3
    • 4
    (5)配置事务的通知引用事务管理器
    
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    
    tx:advice>
    
    • 1
    • 2
    • 3
    • 4
    (6)配置事务的属性
    
    <tx:attributes>
        <tx:method name="*"/>
    tx:attributes>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    (7)配置 AOP 切入点表达式
    
    <aop:config>
        <aop:pointcut id="myPointcut" expression="execution(* com.offcn.service.impl.*.*(..))"/>
    aop:config>
    
    • 1
    • 2
    • 3
    • 4
    (8) 配置切入点表达式和事务通知的对应关系
    
    <aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut">aop:advisor>
    
    • 1
    • 2

    第17节:Spring事务详解-注解

    17.1 基于注解的事务配置
    17.1.1 添加相关技术依赖
    <properties>
        <spring.version>5.2.5.RELEASEspring.version>
    properties>
    <dependencies>
        
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
            <scope>testscope>
        dependency>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>${spring.version}version>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-testartifactId>
            <version>${spring.version}version>
        dependency>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-jdbcartifactId>
            <version>${spring.version}version>
        dependency>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.47version>
        dependency>
        
        <dependency>
            <groupId>com.mchangegroupId>
            <artifactId>c3p0artifactId>
            <version>0.9.5.2version>
        dependency>
        
        <dependency>
            <groupId>org.aspectjgroupId>
            <artifactId>aspectjweaverartifactId>
            <version>1.8.7version>
        dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    17.1.2 创建配置文件导入约束
    <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:aop="http://www.springframework.org/schema/aop"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        
        <context:component-scan base-package="com.offcn">context:component-scan>
    
        
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            
            <property name="driverClass" value="com.mysql.jdbc.Driver">property>
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test">property>
            <property name="user" value="root">property>
            <property name="password" value="root">property>
        bean>
        
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource">property>
        bean>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    17.1.3 沿用转账业务的代码
    17.2 事务管理配置步骤(重点)
    17.2.1 配置事务管理器并注入数据源
     
    <bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource">property>
    bean>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    17.2.2 在业务层使用注解
    /**
     该注解的属性和 xml 中的属性含义一致。该注解可以出现在接口上,类上和方法上。
     出现接口上,表示该接口的所有实现类都有事务支持。
     出现在类上,表示类中所有方法有事务支持
     出现在方法上,表示方法有事务支持。
     以上三个位置的优先级:方法>类>接口 
     */
    @Service("accountService")
    @Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
    public class AccountServiceImpl implements AccountService {
        //依赖dao层
        @Autowired
        private AccountDao accountDao ;
    
        @Transactional(readOnly = false,propagation = Propagation.REQUIRED)
        @Override
        public void transfer(String sourceAccountName, String targetAccountName, Double money) {
                Account sAccount = accountDao.findByName(sourceAccountName);
                Account tAccount = accountDao.findByName(targetAccountName);
    
                //来源账户减钱,目标账户加钱
                sAccount.setMoney(sAccount.getMoney()-money);
                tAccount.setMoney(tAccount.getMoney()+money);
    
                //持久化到数据库
                accountDao.update(sAccount);
                //模拟异常发生
                //int i=1/0;
                accountDao.update(tAccount);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    17.2.3 在配置文件中开启注解事务
     
    <tx:annotation-driven transaction-manager="transactionManager"/>
    
    
    • 1
    • 2
    • 3
    17.3 Spring事务源码分析(了解)
    17.3.1 DataSourceUtils源码分析
    		看名字就能知道这个类是对DataSource的一个封装,这个类提供了一系列操作数据库连接的工具方法。这个类在Spring事务中非常重要,最主要的作用就是提供了能够从当前线程获取开启事务时绑定的连接。其中Spring Jdbc里的JdbcTemplate类就是采用DataSourceUtils.getConnection()方法获取连接的。
    
    • 1
    public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException {
            try {
                return doGetConnection(dataSource);
            } catch (SQLException var2) {
                throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection", var2);
            } catch (IllegalStateException var3) {
                throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection: " + var3.getMessage());
            }
        }
    
        public static Connection doGetConnection(DataSource dataSource) throws SQLException {
            Assert.notNull(dataSource, "No DataSource specified");
            ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(dataSource);
            if (conHolder == null || !conHolder.hasConnection() && !conHolder.isSynchronizedWithTransaction()) {
                logger.debug("Fetching JDBC Connection from DataSource");
                Connection con = fetchConnection(dataSource);
                if (TransactionSynchronizationManager.isSynchronizationActive()) {
                    try {
                        ConnectionHolder holderToUse = conHolder;
                        if (conHolder == null) {
                            holderToUse = new ConnectionHolder(con);
                        } else {
                            conHolder.setConnection(con);
                        }
    
                        holderToUse.requested();
                        TransactionSynchronizationManager.registerSynchronization(new DataSourceUtils.ConnectionSynchronization(holderToUse, dataSource));
                        holderToUse.setSynchronizedWithTransaction(true);
                        if (holderToUse != conHolder) {
                            TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
                        }
                    } catch (RuntimeException var4) {
                        releaseConnection(con, dataSource);
                        throw var4;
                    }
                }
    
                return con;
            } else {
                conHolder.requested();
                if (!conHolder.hasConnection()) {
                    logger.debug("Fetching resumed JDBC Connection from DataSource");
                    conHolder.setConnection(fetchConnection(dataSource));
                }
    
                return conHolder.getConnection();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    17.3.2 TransactionSynchronizationManager源码分析
    	这个类的作用就是绑定资源到当前线程、注册TransactionSynchronization接口、绑定事务的各个属性。
    
    • 1
    public abstract class TransactionSynchronizationManager {
        private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations = new NamedThreadLocal("Transaction synchronizations");
    
        public static void initSynchronization() throws IllegalStateException {
            if (isSynchronizationActive()) {
                throw new IllegalStateException("Cannot activate transaction synchronization - already active");
            } else {
                logger.trace("Initializing transaction synchronization");
                synchronizations.set(new LinkedHashSet());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    第18节:Spring整合Mybatis(重点)

    18.1 整合思路分析
    		Mybatis框架是一个持久层ORM框架,而Spring则是一个综合性一站式框架。所以整合是MybatisSpring上整合。就是让Spring框架接管Mybatis的组件。
    
    		Mybatis单独运行时,数据源的管理,事务的管理, SqlSessionFactory 以及接口的实现类都是Mybatis管理的,整合后以上组件交给Spring管理。
    
    
    • 1
    • 2
    • 3
    • 4
    18.2 添加技术依赖
    <properties>
        <spring.version>5.2.5.RELEASEspring.version>
    properties>
    <dependencies>
        
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
            <scope>testscope>
        dependency>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>${spring.version}version>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-testartifactId>
            <version>${spring.version}version>
        dependency>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-jdbcartifactId>
            <version>${spring.version}version>
        dependency>
        
        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.47version>
        dependency>
        
        <dependency>
            <groupId>com.mchangegroupId>
            <artifactId>c3p0artifactId>
            <version>0.9.5.2version>
        dependency>
        
        <dependency>
            <groupId>org.aspectjgroupId>
            <artifactId>aspectjweaverartifactId>
            <version>1.8.7version>
        dependency>
    
        
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatis-springartifactId>
            <version>2.0.0version>
        dependency>
        
        <dependency>
            <groupId>org.mybatisgroupId>
            <artifactId>mybatisartifactId>
            <version>3.4.6version>
        dependency>
    dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    18.3 构建数据库表并创建实体User
    create table User(
     id int primary key auto_increment,
     name varchar(32) not null,
     address varchar(32) not null,
     birthday date 
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    public class User implements Serializable {
        private Integer id;
        private String name;
        private String address;
        private Date birthday;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", address='" + address + '\'' +
                    ", birthday=" + birthday +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    18.4 编写dao层的接口UserMapper
    public interface UserMapper {
        int insert(User user);
        int update(User user);
        int delete(Integer id);
        User findById(Integer id);
        List<User> findAll();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    18.5 构建mapper接口对应的sql配置文件
    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.offcn.mapper.UserMapper">
        <resultMap id="BaseResultMap" type="com.offcn.pojo.User">
            <id column="id" jdbcType="INTEGER" property="id" />
            <result column="name" jdbcType="VARCHAR" property="name" />
            <result column="address" jdbcType="VARCHAR" property="address" />
            <result column="birthday" jdbcType="DATE" property="birthday" />
        resultMap>
    
        <insert id="insert" parameterType="com.offcn.pojo.User">
            insert into user (name, birthday, address)
            values (#{name}, #{birthday},#{address})
        insert>
    
        <update id="update">
            update user
            set
            name= #{name},
            birthday=#{birthday},
            address = #{address}
            where id=#{id}
        update>
    
        <delete id="delete">
            delete from user
            where id =#{id}
        delete>
    
        <select id="findById" resultMap="BaseResultMap">
            select * from user where id=#{id}
        select>
    
        <select id="findAll" resultMap="BaseResultMap">
            select * from user
        select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    18.6 构建服务层接口UserService
    public interface UserService {
        int insert(User user);
        int update(User user);
        int delete(Integer id);
        User findById(Integer id);
        List<User> findAll();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    18.7 构建服务层实现类UserServiceImpl
    @Service
    public class UserServiceImpl implements UserService {
    
        @Autowired
        private UserMapper userMapper;
        @Override
        public int insert(User user) {
            int num = userMapper.insert(user);
            return  num;
        }
    
        @Override
        public int update(User user) {
            int num = userMapper.update(user);
            return num;
        }
    
        @Override
        public int delete(Integer id) {
            int num = userMapper.delete(id);
            return num;
        }
    
        @Override
        public User findById(Integer id) {
            User user = userMapper.findById(id);
            return user;
        }
    
        @Override
        public List<User> findAll() {
            List<User> userList = userMapper.findAll();
            return userList;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    18.8 构建Spring框架的配置文件配置IOC管理的对象【重点】
    <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"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    
        
        <context:component-scan base-package="com.offcn"> context:component-scan>
    
        
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            
            <property name="driverClass" value="com.mysql.jdbc.Driver">property>
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test">property>
            <property name="user" value="root">property>
            <property name="password" value="root">property>
        bean>
    
        
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            
            <property name="dataSource" ref="dataSource"/>
            
            <property name="mapperLocations" value="classpath:com/offcn/mapper/*Mapper.xml">property>
            
            <property name="configLocation" value="classpath:SqlMapConfig.xml"/>
    
            
            <property name="typeAliasesPackage" value="com/offcn/pojo"/>
            
            <property name="plugins">
    			<array>
    				<bean class="com.github.pagehelper.PageInterceptor">
    					<property name="properties">
    						<value>
    							helperDialect=MySQL
    							reasonable=true
    							supportMethodsArguments=true
    							params=count=countSql
    							autoRuntimeDialect=true
    						value>
    					property>
    				bean>
    			array>
    		property>   
        bean>
    
        
        <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            
            <property name="basePackage" value="com.offcn.mapper">property>
        bean>
    
        
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            
            <property name="dataSource" ref="dataSource"/>
        bean>
        <tx:annotation-driven transaction-manager="transactionManager"/>
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    18.9 测试代码
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class TestAccountTransfer {
    
        @Autowired
        private UserService userService;
    
        //save
        @Test
        public void testInsert(){
            User user = new User();
            user.setName("admin");
            user.setAddress("china");
            user.setBirthday(new Date());
            int num = userService.insert(user);
            System.out.println("num:"+num);
        }
        //update
        @Test
        public void testUpdate(){
            User user = new User();
            user.setName("marry");
            user.setAddress("America");
            user.setBirthday(new Date());
            user.setId(1);
            int num = userService.update(user);
            System.out.println("num:"+num);
        }
    
        //delete:
        @Test
        public void testDelete(){
            int num = userService.delete(1);
            System.out.println("num:"+num);
        }
    
        //findById
        @Test
        public void testFindById(){
            User user = userService.findById(2);
            System.out.println("user:"+user);
        }
        //findAll
        @Test
        public void testFindByAll(){
            List<User> userList = userService.findAll();
            System.out.println("userList:"+userList);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
  • 相关阅读:
    【数据结构算法】动态规划之【单序列问题】
    第一个Spring程序
    基于反熔丝FPGA、QSPI FLASH的高可靠程序存储、启动控制系统
    SpringBoot中使用Redis实现分布式锁
    机器学习笔记 - 自相关和偏自相关简介
    98. 一台服务器能支持多少QPS
    mysql数据库
    MySQL中的多列子查询
    WFST--学习笔记
    【计算机网络】应用层
  • 原文地址:https://blog.csdn.net/sjxxxx_/article/details/127625086