• spring的学习【3】


    前言

    SpringFamework的学习,是小编正在经历的,作为刚刚接触这玩意的新人,也算是摸爬滚打一路奔跑
    与君共勉!!!
    本文的学习学自狂神说,大家可以在B站找到!赞!狂神说!!在这里插入图片描述

    十 AOP

    10.1 什么是AOP?

    AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现
    程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的
    一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使
    得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

    在这里插入图片描述
    本图借自狂神的笔记

    10.2 Aop在Spring中的作用

    • 提供声明式事务;允许用户自定义切面
      • 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要
      • 关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 …
      • 切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类。
      • 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
      • 目标(Target):被通知对象。
      • 代理(Proxy):向目标对象应用通知之后创建的对象。
      • 切入点(PointCut):切面通知 执行的 “地点”的定义。
      • 连接点(JointPoint):与切入点匹配的执行点
        在这里插入图片描述
        SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:
    通知类型连接点实现接口
    前置通知方法方法前org.springframework.aop.MethodBeforeAdvice
    方法后后置通知org.springframework.aop.AfterReturningAdvice
    环绕通知方法前后org.aopalliance.intercept.MethodInterceptor
    方法抛出异常异常抛出通知org.springframework.aop.ThrowsAdvice
    引介通知类中增加新的方法属性orgspringframework.aop.Introductionlnterceptor

    即 Aop 在 不改变原有代码的情况下 , 去增加新的功能 .

    10.3 使用spring实现Aop

    • 使用AOP织入,需要导入一个依赖包!
    <dependencies>
            
            <dependency>
                <groupId>org.aspectjgroupId>
                <artifactId>aspectjweaverartifactId>
                <version>1.9.9.1version>
            dependency>
        dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    第一种方式 通过 Spring API 实现

    • 业务接口和实现类
    package com.yang.service;
    
    /**
     * @author 缘友一世
     * @date 2022/7/27-20:40
     */
    public interface UserService {
        public void add();
        public void delete();
        public void update();
        public void query();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    package com.yang.service;
    
    /**
     * @author 缘友一世
     * @date 2022/7/27-20:42
     */
    public class UserServiceImpl implements UserService {
    
        public void add() {
            System.out.println("add a user");
        }
    
        public void delete() {
            System.out.println("delete a user");
        }
    
        public void update() {
            System.out.println("update a user");
        }
    
        public void query() {
            System.out.println("query a user ");
        }
    }
    
    
    • 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
    • 增强类 , 一个前置增强 一个后置增强
    package com.yang.log;
    
    import org.springframework.aop.AfterReturningAdvice;
    
    import java.lang.reflect.Method;
    
    /**
     * @author 缘友一世
     * @date 2022/7/27-20:53
     */
    public class AfterLog implements AfterReturningAdvice {
        //method : 要执行的目标对象的方法
        //objects : 被调用的方法的参数
        //Object : 目标对象
        public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
            System.out.println("执行了"+method.getName()+"方法,返回结果:"+returnValue);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    package com.yang.log;
    
    import org.springframework.aop.MethodBeforeAdvice;
    
    import java.lang.reflect.Method;
    
    /**
     * @author 缘友一世
     * @date 2022/7/27-20:47
     */
    public class BeforeLog implements MethodBeforeAdvice {
        //method:要执行的目标对象的方法
        //args:被调用的方法的对象的参数
        //target:目标读写;被调用的目标对象
        //returnValue 返回值
        public void before(Method method, Object[] args, Object target) throws Throwable {
            System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 最后去spring的文件中注册 , 并实现aop切入实现 , 注意导入约束 .
    
    <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
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
        
        <bean id="userService" class="com.yang.service.UserServiceImpl"/>
        <bean id="log" class="com.yang.log.BeforeLog"/>
        <bean id="after" class="com.yang.log.AfterLog"/>
    
        
        
        <aop:config>
            
            <aop:pointcut id="pointCut" expression="execution(* com.yang.service.UserServiceImpl.*(..))"/>
            
            
            <aop:advisor advice-ref="log" pointcut-ref="pointCut"/>
            <aop:advisor advice-ref="after" pointcut-ref="pointCut"/>
        aop:config>
    
    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

    狂神的话:

    • Aop的重要性 : 很重要 . 一定要理解其中的思路 , 主要是思想的理解这一块 .
    • Spring的Aop就是将公共的业务 (日志 , 安全等) 和领域业务结合起来 , 当执行领域业务时 , 将会把公共业务加进来 . 实现公共业务的重复利用 . 领域业务更纯粹 , 程序猿专注领域业务 , 其本质还是动态代理

    第二种方式 自定义类来实现Aop

    • 目标业务类不变依旧是userServiceImpl
    • 第一步:DIY一个切入类
    package com.yang.diy;
    
    /**
     * @author 缘友一世
     * @date 2022/7/28-14:41
     */
    public class DIyPointCut {
        public void before() {
            System.out.println("====执行方法前====");
        }
        public void after() {
            System.out.println("====执行方法后====");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • spring配置
    	
    	
        <bean id="diy" class="com.yang.diy.DIyPointCut"/>
    	
    	
        <aop:config>
            
            <aop:aspect ref="diy">
                
                
                <aop:pointcut id="point" expression="execution(* com.yang.service.UserServiceImpl.*(..))"/>
                
                <aop:before method="before" pointcut-ref="point"/>
                <aop:after method="after" pointcut-ref="point"/>
            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
    import com.yang.service.UserService;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @author 缘友一世
     * @date 2022/7/27-21:15
     */
    public class MyTest09 {
        public static void main(String[] args) {
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
            //动态代理代理的是接口:注意点
            UserService userService = (UserService) context.getBean("userService");
            userService.query();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    第三种方法 使用注解实现

    • 第一步:编写一个注解实现的增强类
    package com.yang.diy;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    
    /**
     * @author 缘友一世
     * @date 2022/7/28-14:58
     */
    //方式三:使用注解方式实现AOP
    @Aspect//标注此类是一个切面
    public class AnnotationPointCut {
        @Before("execution(* com.yang.service.UserServiceImpl.*(..))")
        public void before() {
            System.out.println("==方法执行前==");
        }
        @After("execution(* com.yang.service.UserServiceImpl.*(..))")
        public void after() {
            System.out.println("==方法执行后==");
        }
        //在环绕增强中,可以定义一个参数,代表要获取处理的切入点
        @Around("execution(* com.yang.service.UserServiceImpl.*(..))")
        public void around(ProceedingJoinPoint jp) throws Throwable {
            Signature signature = jp.getSignature();//获取签名
            System.out.println("signature"+signature);
            System.out.println("环绕前");
            Object proceed = jp.proceed();//执行方法
    
            System.out.println("环绕后");
            System.out.println(proceed);
        }
        /*
        * signaturevoid com.yang.service.UserService.query()
        环绕前
        ==方法执行前==
        query a user
        ==方法执行后==
        环绕后
        null*/
    }
    
    
    • 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
    • 第二步:在Spring配置文件中,注册bean,并增加支持注解的配置
        
        <bean id="annotationPointCut" class="com.yang.diy.AnnotationPointCut"/>
        
        <aop:aspectj-autoproxy/>
    
    • 1
    • 2
    • 3
    • 4
      通过aop命名空间的<aop:aspectj-autoproxy />声明自动为spring容器中那些配置@aspectJ切面
    的bean创建代理,织入切面。当然,spring 在内部依旧采用
    AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被
    <aop:aspectj-autoproxy />隐藏起来了
      <aop:aspectj-autoproxy />有一个proxy-target-class属性,默认为false,表示使用jdk动态
    代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class="true"/>时,表示使用
    CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接
    口,则spring将自动使用CGLib动态代理。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    十一 整合Mybatis

    11.1 准备:导包

    • junit
    <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>4.11version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • mybatis
    <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatisartifactId>
                <version>3.5.6version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • mysql-connector-java
    <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>8.0.29version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • spring相关
    <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-webmvcartifactId>
                <version>5.3.18version>
            dependency>
            
            
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-jdbcartifactId>
                <version>5.3.20version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • aspectj AOP 织入器
    <dependency>
                <groupId>org.aspectjgroupId>
                <artifactId>aspectjweaverartifactId>
                <version>1.9.9.1version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • mybatis-spring整合包 【重点】
    <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatis-springartifactId>
                <version>2.0.7version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 配置Maven静态资源过滤问题!
     <build>
            <resources>
                <resource>
                    <directory>src/main/javadirectory>
                    <includes>
                        <include>**/*.propertiesinclude>
                        <include>**/*.xmlinclude>
                    includes>
                    <filtering>truefiltering>
                resource>
                <resource>
                    <directory>src/main/resourcesdirectory>
                    <includes>
                        <include>**/*.propertiesinclude>
                        <include>**/*.xmlinclude>
                    includes>
                    <filtering>truefiltering>
                resource>
            resources>
        build>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 当然还有我们的偷懒小工具
    <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
                <version>1.18.24version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    11.2 编写配置文件

    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
        
        <properties resource="db.properties"/>
    
        
        <settings>
            <setting name="logImpl" value="STDOUT_LOGGING"/>
            
            <setting name="mapUnderscoreToCamelCase" value="true"/>
        settings>
    
        
        <typeAliases>
            <package name="com.yang.pojo"/>
        typeAliases>
        <environments default="development">
            <environment id="development">
                
                <transactionManager type="JDBC"/>
                
                <dataSource type="POOLED">
                    <property name="driver" value="${driver}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${username}"/>
                    <property name="password" value="${password}"/>
                dataSource>
            environment>
        environments>
    
        <mappers>
           <package name="com.yang.dao"/>
        mappers>
    configuration>
    
    • 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
    • 编写pojo实体类
    package com.yang.pojo;
    
    import lombok.Data;
    
    /**
     * @author 缘友一世
     * @date 2022/7/28-15:44
     */
    @Data
    public class User {
        private int id;
        private String name;
        private String pwd;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • UserDao接口编写
    public interface UserMapper {
         List<User> selectUser1();
    }
    
    • 1
    • 2
    • 3
    • 接口对应的Mapper映射文件
    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.yang.mapper.UserMapper">
    
        <select id="selectUser1" resultType="com.yang.pojo.User">
            select *
            from mybatis.user;
        select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    11.3 测试类

    import com.yang.mapper.UserMapper;
    import com.yang.pojo.User;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @author 缘友一世
     * @date 2022/7/28-15:57
     */
    public class MyTest10 {
        @Test
        public void test1() {
            ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationText.xml");
            UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);
            for(User user:userMapper.selectUser1())
            {
                System.out.println(user);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    11.4 MyBatis-Spring学习

    • 什么是 MyBatis-Spring?
      • MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。
    • 知识基础
      在开始使用 MyBatis-Spring 之前,你需要先熟悉 Spring 和 MyBatis 这两个框架和有关它们的术。
      • MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
      • Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。
    • MyBatis-Spring 需要以下版本:
    MyBatis-SpringMyBatis Spring 框架Spring BatchJava
    2.03.5+5.0+4.0+
    1.33.4+3.2.2+2.1+
    • 使用 Maven 作为构建工具,仅需要在 pom.xml 中加入以下代码即可
    dependency>
            
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatis-springartifactId>
                <version>2.0.7version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 要和 Spring 一起使用 MyBatis,需要在 Spring 应用上下文中定义至少两样东西:一个SqlSessionFactory至少一个数据映射器类。
    • 在 MyBatis-Spring 中,可使用 SqlSessionFactoryBean 来创建== SqlSessionFactory ==。 要配置
      这个工厂 bean,只需要把下面代码放在 Spring 的 XML 配置文件中:
    
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="datasource" />
        bean>
    
    • 1
    • 2
    • 3
    • 4

    11.5 枯燥环节

    注意: SqlSessionFactory 需要一个 DataSource (数据源)。 这可以是任意的DataSource ,只需要和配置其它 Spring 数据库连接一样配置它就可以了。

    • 在基础的 MyBatis 用法中,是通过 SqlSessionFactoryBuilder 来创建 SqlSessionFactory的。 而在 MyBatis-Spring 中,则使用== SqlSessionFactoryBean== 来创建。

    • 在 MyBatis 中,你可以使用 SqlSessionFactory 来创建 SqlSession 。一旦你获得一个session 之后,你可以使用它来执行映射了的语句,提交或回滚连接,最后,当不再需要它的时候,你可以关闭 session。

    • SqlSessionFactory 有一个唯一的必要属性:用于 JDBC 的 DataSource 。这可以是任意的DataSource 对象,它的配置方法和其它 Spring 数据库连接是一样的。

    • 一个常用的属性是== configLocation ==,它用来指定 MyBatis 的 XML 配置文件路径。它在需要修改MyBatis 的基础配置非常有用。通常,基础配置指的是 元素。

    • 需要注意的是,这个配置文件并不需要是一个完整的 MyBatis 配置。确切地说,任何环境配置,数据源( )和 MyBatis 的事务管理器( )都会被忽略。 SqlSessionFactoryBean 会创建它自有的 MyBatis环境配置( Environment ),并按要求设置自定义环境的值。SqlSessionTemplate MyBatis-Spring 的核心。作为 SqlSession 的一个实现,这意味着可以使用它无缝代替你代码中已经在使用的== SqlSession ==。

    • 可以使用 ==SqlSessionFactory ==作为构造方法的参数来创建 SqlSessionTemplate 对象。可以使用 SqlSessionFactory 作为构造方法的参数来创建 SqlSessionTemplate 对象。

    
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
            <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 现在,这个 bean 就可以直接注入到你的 DAO bean 中了。你需要在你的 bean 中添加一个 SqlSession属性,就像下面这样:
    package com.yang.mapper;
    
    import com.yang.pojo.User;
    import org.mybatis.spring.SqlSessionTemplate;
    
    import java.util.List;
    
    /**
     * @author 缘友一世
     * @date 2022/7/28-17:03
     */
    public class UserMapperImpl implements UserMapper{
        //我们所有的操作,在原来都使用sqlSession来执行,现在,都使用sqlSessionTemplate;
        private SqlSessionTemplate sqlSession;
    
        public void setSqlSession(SqlSessionTemplate sqlSession) {
            this.sqlSession = sqlSession;
        }
    
        public List<User> selectUser1() {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.selectUser1();
        }
    }
    
    
    • 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
    • 按下面这样,注入 ==SqlSessionTemplate ==:
    <bean id="userMapper" class="com.yang.mapper.UserMapperImpl">
            <property name="sqlSession" ref="sqlSession"/>
        bean>
    
    • 1
    • 2
    • 3

    11.6 整合实现一

      1. 引入Spring配置文件beans.xml
    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
    • 1
    • 2
    • 3
    • 4
    • 5
      1. 配置数据源替换mybaits的数据源
    
        
        <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"/>
            <property name="username" value="root"/>
            <property name="password" value="xxxxxxxx"/>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
      1. 配置SqlSessionFactory,关联MyBatis
    
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="datasource" />
            
            
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
            <property name="mapperLocations" value="classpath:com/yang/mapper/*.xml"/>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
      1. 注册sqlSessionTemplate,关联sqlSessionFactory;
    
        
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
            
            <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
      1. 增加Dao接口的实现类;私有化sqlSessionTemplate
    package com.yang.mapper;
    
    import com.yang.pojo.User;
    import org.mybatis.spring.SqlSessionTemplate;
    
    import java.util.List;
    
    /**
     * @author 缘友一世
     * @date 2022/7/28-17:03
     */
    public class UserMapperImpl implements UserMapper{
        //我们所有的操作,在原来都使用sqlSession来执行,现在,都使用sqlSessionTemplate;
        //私有化sqlSessionTemplate
        //sqlSession不用我们自己创建了,Spring来管理
        private SqlSessionTemplate sqlSession;
    
        public void setSqlSession(SqlSessionTemplate sqlSession) {
            this.sqlSession = sqlSession;
        }
    
        public List<User> selectUser1() {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.selectUser1();
        }
    }
    
    
    • 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
      1. 注册bean实现
    <bean id="userMapper" class="com.yang.mapper.UserMapperImpl">
            <property name="sqlSession" ref="sqlSession"/>
        bean>
    
    • 1
    • 2
    • 3
      1. 测试
    public class MyTest10 {
        @Test
        public void test1() {
            ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationText.xml");
            UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);
            for(User user:userMapper.selectUser1())
            {
                System.out.println(user);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    结果成功输出!现在我们的Mybatis配置文件的状态!发现都可以被Spring整合!
    在这里插入图片描述

    11.7 整合实现二

    • mybatis-spring1.2.3版以上的才有这个
    • 官网地址
    • dao继承Support类 , 直接利用 getSqlSession() 获得 , 然后直接注入SqlSessionFactory . 比起方式1 , 不需要管理SqlSessionTemplate , 而且对事务的支持更加友好 . 可跟踪源码查看
      在这里插入图片描述

    测试应用:

    • UserMapperImpl2.java
    package com.yang.mapper;
    
    import com.yang.pojo.User;
    import org.mybatis.spring.support.SqlSessionDaoSupport;
    
    import java.util.List;
    
    /**
     * @author 缘友一世
     * @date 2022/7/28-18:25
     */
    public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    
        public List<User> selectUser1() {
            return getSqlSession().getMapper(UserMapper.class).selectUser1();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 修改bean的配置
    <bean id="userMapper2" class="com.yang.mapper.UserMapperImpl2">
            <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
        bean>
    
    • 1
    • 2
    • 3
    • 测试
    @Test
        public void test2() {
            ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationText.xml");
            UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);
            for(User user:userMapper.selectUser1())
            {
                System.out.println(user);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    十二 终章:声明式事务

    12.1 回顾事务

    • 事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!
    • 事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性。
    • 事务的原子性:事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。
    事务特性ACID详解
    1. 原子性(atomicity)事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用
    2. 一致性(consistency)一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中
    3. 隔离性(isolation)可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏
    4. 持久性(durability)事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中

    12.2 药引

    • 新建项目,在之前的案例中,给userMapper接口新增两个方法,删除和增加用户;
         //add a user
         int addUser(User user);
         //delete a user
         int deleteUser(int id);
    
    • 1
    • 2
    • 3
    • 4
    • mapper文件,我们故意把 deletes 写错,测试!
    <insert id="addUser" parameterType="com.kuang.pojo.User">
    insert into user (id,name,pwd) values (#{id},#{name},#{pwd})
    insert>
    <delete id="deleteUser" parameterType="int">
    deletes from user where id = #{id}
    delete>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 编写接口的实现类,在实现类中,我们去操作一波
    package com.yang.mapper;
    
    import com.yang.pojo.User;
    import org.mybatis.spring.SqlSessionTemplate;
    import org.mybatis.spring.support.SqlSessionDaoSupport;
    
    import java.util.List;
    
    /**
     * @author 缘友一世
     * @date 2022/7/28-17:03
     */
    public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
    
    
        public List<User> selectUser1() {
            User user1 = new User(5, "西瓜姑娘", "852963741");
            UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
            mapper.addUser(user1);
            mapper.deleteUser(5);
            return mapper.selectUser1();
    
        }
    
        public int addUser(User user) {
            return getSqlSession().getMapper(UserMapper.class).addUser(user);
        }
    
        public int deleteUser(int id) {
            return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
        }
    }
    
    • 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
    • 测试
    public class MyTest11 {
        //本次实验为引出事务管理器
        //delete语句有错误,但是add事务执行了,提交到了数据库,成功了一般,违反事务的原子性
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext11.xml");
            UserMapper userMapper = context.getBean("UserMapper", UserMapper.class);
            List<User> users = userMapper.selectUser1();
            for(User user:users) {
                System.out.println(user);
            }
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 报错:sql异常,delete写错了
    • 结果 :插入成功!
      在这里插入图片描述
    • 没有进行事务的管理;我们想让他们都成功才成功,有一个失败,就都失败,我们就应该需要事务!
    • 以前我们都需要自己手动管理事务,十分麻烦!但是Spring给我们提供了事务管理,我们只需要配置即可。

    12.3 Spring中的事务管理

    • Spring在不同的事务管理API之上定义了一个抽象层,使得开发人员不必了解底层的事务管理API就可以
      使用Spring的事务管理机制。Spring支持编程式事务管理和声明式的事务管理。
    • 编程式事务管理
      • 将事务管理代码嵌到业务方法中来控制事务的提交和回滚
      • 缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码
    • 声明式事务管理
      • 一般情况下比编程式事务好用。
      • 将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理
      • 将事务管理作为横切关注点,通过aop方法模块化Spring中通过Spring AOP框架支持声明式事务管理。
    • 使用Spring管理事务,注意头文件的约束导入 : tx
    xmlns:tx="http://www.springframework.org/schema/tx"
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    
    • 1
    • 2
    • 3
    • 事务管理器
      • 无论使用Spring的哪种事务管理策略(编程式或者声明式)事务管理器都是必须的。
      • 就是 Spring的核心事务管理抽象,管理封装了一组独立于技术的方法。
    • JDBC事务
    
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="datasource"/>
        bean>
    
    • 1
    • 2
    • 3
    • 4
    • 配置好事务管理器后我们需要去配置事务的通知
    
        
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            
            
            <tx:attributes>
                <tx:method name="add" propagation="REQUIRED"/>
                <tx:method name="delete" propagation="REQUIRED"/>
                <tx:method name="update" propagation="REQUIRED"/>
                <tx:method name="query" read-only="true"/>
                <tx:method name="*" propagation="REQUIRED"/>
            tx:attributes>
        tx:advice>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • spring事务传播特性:
    • 事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。spring支持7种事务传播行
      为:
    传播行为分类详解
    propagation_requierd如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择。
    propagation_supports支持当前事务,如果没有当前事务,就以非事务方法执行。
    propagation_mandatory使用当前事务,如果没有当前事务,就抛出异常。
    propagation_required_new新建事务,如果当前存在事务,把当前事务挂起。
    propagation_not_supported以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
    propagation_never以非事务方式执行操作,如果当前事务存在则抛出异常。
    propagation_nested如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作
    • Spring 默认的事务传播行为是 PROPAGATION_REQUIRED,它适合于绝大多数的情况。
    • 假设 ServiveX#methodX() 都工作在事务环境下(即都被 Spring 事务增强了),假设程序中存在如下的调用链:
      Service1#method1()->Service2#method2()->Service3#method3(),
      那么这 3 个服务类的 3个方法通过 Spring 的事务传播机制都工作在同一个事务中。
    • 就好比,我们刚才的几个方法存在调用,所以会被放在一组事务当中!
    • 配置AOP
     
        
        <aop:config>
            <aop:pointcut id="txPointCut" expression="execution(* com.yang.mapper.*.*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
        aop:config>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 进行测试
      删掉刚才插入的数据,再次测试!
    public class MyTest11 {
        //本次实验为引出事务管理器
        //delete语句有错误,但是add事务执行了,提交到了数据库,成功了一般,违反事务的原子性
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext11.xml");
            UserMapper userMapper = context.getBean("UserMapper", UserMapper.class);
            List<User> users = userMapper.selectUser1();
            for(User user:users) {
                System.out.println(user);
            }
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 执行失败,数据库未改变
      在这里插入图片描述
      在这里插入图片描述

    12.4 反思配置事务的意义

    • 如果不配置,就需要我们手动提交控制事务;
    • 事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!

    后记

    • 终于,跌跌撞撞将spring入门了,文章基于狂神的笔记,相当于有复习了一遍,但是仍有很多不足,希望读者朋友不要怪罪!!
    • 踏踏实实做人,认真认真做事。相信我们的付出,都会成为我们生命中的勋章!!
    • 愿君,勇攀高峰,遇见不一样的未来,不一样的自己……
      在这里插入图片描述
  • 相关阅读:
    Leetcode 1584. 连接所有点的最小费用(手撸普利姆算法)
    Linux内核子系统 内核配置选项
    阿里云国际站云计算-负载均衡SLB介绍-unirech
    Django(1)编写你的第一个Django应用
    【JavaEE---复习】一、.Spring的Ioc和DI
    设计模式(十五)----结构型模式之外观模式
    minio搭建文件存储服务
    【深度学习】04-01-自注意力机制(Self-attention)-李宏毅老师21&22深度学习课程笔记
    八道简单入门编程题详解+拓展(水花仙,二进制序列……)
    Swift编写爬取商品详情页面的爬虫程序
  • 原文地址:https://blog.csdn.net/yang2330648064/article/details/126052892