• 【深入浅出Spring6】第十期——尾声


    一、Spring集成了Junit

    • 之前我们只是使用Junit的测试注解 @Test,并没有使用Spring对于Junit的支持

    • Spring6既支持Junit4、也支持Spring5

    • 要想使用Spring对于Junit的支持,我们需要在pom中导入相关依赖

      <!--我们引入Spring对junit支持的依赖 >> 既支持Junit4、也支持Junit5-->
      <dependency>
      	<groupId>org.springframework</groupId>
      	<artifactId>spring-test</artifactId>
      	<version>6.0.0-M2</version>
      </dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

      因为 Spring6 还没有正式发布,所以我们需要配置对应的远程仓库

      <!--仓库-->
      <repositories>
      	<!--spring里程碑版本的仓库-->
      	<repository>
      		<id>repository.spring.milestone</id>
      		<name>Spring Milestone Repository</name>
      		<url>https://repo.spring.io/milestone</url>
      	</repository>
      </repositories>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    • 上面对Junit支持的依赖是既可以用于Junit4、也可以用于Junit5的,我们选择使用4还是5只需要导入相关依赖

      <!--junit5依赖-->
      <dependency>
      	<groupId>org.junit.jupiter</groupId>
      	<artifactId>junit-jupiter</artifactId>
      	<version>5.9.0</version>
      	<scope>test</scope>
      </dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      <!--junit4依赖-->
      <dependency>
      	<groupId>junit</groupId>
      	<artifactId>junit</artifactId>
      	<version>4.13.2</version>
      	<scope>test</scope>
      </dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 为了具体演示测试类的不同,我们编写一个User类,提供一个获取名字的方法

    编写我们的 User

    package com.powernode.spring6.bean;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.stereotype.Component;
    
    /**
     * @author Bonbons
     * @version 1.0
     */
    @Component
    public class User {
        // 我们只提供一个属性
        @Value("华佗")
        private String name;
    
        public User() {
        }
    
        public User(String name) {
            this.name = name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    
    • 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

    编写我们的配置文件 >> 因为我们采用注解恶毒方式声明Bean和注入属性值,所以需要扫描一下

    <?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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <!--因为我们采用的是注解注入,所以需要context命名空间扫描包-->
        <context:component-scan base-package="com.powernode.spring6.bean" />
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    我们先编写一下我们使用Junit4支持的测试类

    package com.powernode.spring6.test;
    
    import com.powernode.spring6.bean.User;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    /**
     * @author Bonbons
     * @version 1.0
     */
    @RunWith(SpringJUnit4ClassRunner.class) //RunWith是一个运行器,我们可以指定让Junit4来运行
    @ContextConfiguration("classpath:spring.xml") // 该注解声明我们配置文件的位置,类中所有方法都可以直接使用Spring容器
    public class SpringJunit4Test {
        // 可以直接创建全局对象 >> 使用@Autowired注解按类型注入
        @Autowired
        private User user;
        @Test
        public void testUser(){
            /*
                我们每次进行单元测试都要获取Spring容器,然后通过getBean获取对象实例 >> 很不方便
                Spring对Junit4提供了支持,我们直接可以给我们的测试类添加两个注解 >> 代替这些繁琐的步骤
    
             */
            /*
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            User user = applicationContext.getBean("user", User.class);
            System.out.println(user.getName());
             */
    
            // 以上注释掉的代码可以用下面的代替
            System.out.println(user.getName());
        }
    }
    
    • 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
    • 很明显在我们的测试类上方添加了两个注解:
      • @RunWith 注解代表我们使用Junit4的运行器去运行
      • @ContextConfiguration 注解代表告诉我们的容器配置文件的位置

    在这里插入图片描述

    编写我们 Junit5 的测试类 >> 我们需要在pom.xml中使用SpringJunit支持的依赖以及Junit5的依赖

    package com.powernode.spring6.test;
    
    import com.powernode.spring6.bean.User;
    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.api.extension.ExtendWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit.jupiter.SpringExtension;
    
    
    
    /**
     * @author Bonbons
     * @version 1.0
     */
    @ExtendWith(SpringExtension.class)
    @ContextConfiguration("classpath:spring.xml")
    public class SpringJunit5Test {
        // 直接将User类作为成员变量使用
        @Autowired
        private User user;
        @Test
        public void testUser(){
            System.out.println(user.getName());
        }
    }
    
    • 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

    在这里插入图片描述

    • Junit4不同,Junit5不使用RunWith注解,而是使用ExtendWith注解【具体配置看我们上面的代码】

    二、Spring6集成了MyBatis

    • 我们要演示一个 Spring + MyBatis 的银行转账案例
    • 整个过程包含以下操作:
      ● 第一步:准备数据库表
      ○ 使用t_act表(账户表)
      ● 第二步:IDEA中创建一个模块,并引入依赖
      ○ spring-context
      ○ spring-jdbc
      ○ mysql驱动
      ○ mybatis
      ○ mybatis-spring:mybatis提供的与spring框架集成的依赖
      ○ 德鲁伊连接池
      ○ junit
      ● 第三步:基于三层架构实现,所以提前创建好所有的包
      ○ com.powernode.bank.mapper
      ○ com.powernode.bank.service
      ○ com.powernode.bank.service.impl
      ○ com.powernode.bank.pojo
      ● 第四步:编写pojo
      ○ Account,属性私有化,提供公开的setter getter和toString。
      ● 第五步:编写mapper接口
      ○ AccountMapper接口,定义方法
      ● 第六步:编写mapper配置文件
      ○ 在配置文件中配置命名空间,以及每一个方法对应的sql。
      ● 第七步:编写service接口和service接口实现类
      ○ AccountService
      ○ AccountServiceImpl
      ● 第八步:编写jdbc.properties配置文件
      ○ 数据库连接池相关信息
      ● 第九步:编写mybatis-config.xml配置文件
      ○ 该文件可以没有,大部分的配置可以转移到spring配置文件中。
      ○ 如果遇到mybatis相关的系统级配置,还是需要这个文件。
      ● 第十步:编写spring.xml配置文件
      ○ 组件扫描
      ○ 引入外部的属性文件
      ○ 数据源
      ○ SqlSessionFactoryBean配置
      ■ 注入mybatis核心配置文件路径
      ■ 指定别名包
      ■ 注入数据源
      ○ Mapper扫描配置器
      ■ 指定扫描的包
      ○ 事务管理器DataSourceTransactionManager
      ■ 注入数据源
      ○ 启用事务注解
      ■ 注入事务管理器
      ● 第十一步:编写测试程序,并添加事务,进行测试

    在数据库中准备一张操作的表,我们还是使用 t_act2

    在这里插入图片描述

    创建一个新的模块 spring6-016-sm,并完成相关依赖的配置

    <?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.powernode</groupId>
        <artifactId>spring6-016-sm</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <!--仓库-->
        <repositories>
            <!--spring里程碑版本的仓库-->
            <repository>
                <id>repository.spring.milestone</id>
                <name>Spring Milestone Repository</name>
                <url>https://repo.spring.io/milestone</url>
            </repository>
        </repositories>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>6.0.0-M2</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>6.0.0-M2</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.30</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.11</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
                <version>2.0.7</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.2.13</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.13.2</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <properties>
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    
    </project>
    
    • 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

    采用MVC三层架构建包 >> 但是我们还是Jar项目,以测试程序代替表现层 【我直接给出了所有文件的目录结构】

    在这里插入图片描述

    编写我们的普通 java 类 >> 用来封装我们数据库表中的字段 Account

    package com.powernode.bank.pojo;
    
    /**
     * @author Bonbons
     * @version 1.0
     */
    public class Account {
        private String actno;
        private Double balance;
    
        public Account() {
        }
    
        public Account(String actno, Double balance) {
            this.actno = actno;
            this.balance = balance;
        }
    
        @Override
        public String toString() {
            return "Account{" +
                    "actno='" + actno + '\'' +
                    ", balance=" + balance +
                    '}';
        }
    
        public String getActno() {
            return actno;
        }
    
        public void setActno(String actno) {
            this.actno = actno;
        }
    
        public Double getBalance() {
            return balance;
        }
    
        public void setBalance(Double balance) {
            this.balance = balance;
        }
    }
    
    • 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

    编写我们的Mapper接口 >> 就是对数据库表进行操作的接口,我们采用,MyBatis为我们提供了接口可以动态生成Mapper实现类

    package com.powernode.bank.mapper;
    
    import com.powernode.bank.pojo.Account;
    
    import java.util.List;
    
    /**
     * @author Bonbons
     * @version 1.0
     */
    public interface AccountMapper {
        // 提供简单的增删改查
        int insert(Account account);
        int deleteByActno(String actno);
        int update(Account account);
        Account selectByActno(String actno);
        List<Account> selectAll();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    我们为了一次能导入所有xml配置文件,就将Mapper接口与映射文件放在一个目录下,注意命名的时候用正斜杠

    在这里插入图片描述

    然后编写我们的映射文件 >> 就是写SQL语句的地方 【此处的查询返回值类型我用别名了,因为在核心配置文件中我会开启自动映射】

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <!--需要指定接口的全限定类名-->
    <mapper namespace="com.powernode.bank.mapper.AccountMapper">
        <!--添加数据-->
        <insert id="insert">
            insert into t_act2 values(#{actno}, #{balance})
        </insert>
        <!--删除数据-->
        <delete id="deleteByActno">
            delete from t_act2 where actno = #{actno}
        </delete>
        <!--修改数据-->
        <update id="update">
            update t_act2 set balance = #{balance} where actno = #{actno}
        </update>
        <!--根据账户号查询一条数据-->
        <select id="selectByActno" resultType="Account">
            select * from t_act2 where actno = #{actno}
        </select>
        <!--查询全部数据-->
        <select id="selectAll" resultType="Account">
            select * from t_act2
        </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

    编写业务层的接口 AccountService

    package com.powernode.bank.service;
    
    import com.powernode.bank.pojo.Account;
    
    import java.util.List;
    
    /**
     * @author Bonbons
     * @version 1.0
     */
    public interface AccountService {
        // 添加用户
        int save(Account account);
        // 删除用户
        int delete(String actno);
        // 修改用户信息
        int modify(Account account);
        // 查询一条用户信息
        Account getByActno(String actno);
        // 查询全部的用户信息
        List<Account> getAll();
        // 转账
        void transfer(String fromActno, String toActno, Double money);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    编写我们业务接口的实现类AccountServiceImpl,通过注解纳入Spring IoC 容器托管

    package com.powernode.bank.service.impl;
    
    import com.powernode.bank.mapper.AccountMapper;
    import com.powernode.bank.pojo.Account;
    import com.powernode.bank.service.AccountService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.util.List;
    
    /**
     * @author Bonbons
     * @version 1.0
     */
    @Service("accountService")
    @Transactional
    public class AccountServiceImpl implements AccountService {
        // 引入数据库的操作接口
        @Autowired
        private AccountMapper accountMapper;
        @Override
        public int save(Account account) {
            return accountMapper.insert(account);
        }
    
        @Override
        public int delete(String actno) {
            return accountMapper.deleteByActno(actno);
        }
    
        @Override
        public int modify(Account account) {
            return accountMapper.update(account);
        }
    
        @Override
        public Account getByActno(String actno) {
            return accountMapper.selectByActno(actno);
        }
    
        @Override
        public List<Account> getAll() {
            return accountMapper.selectAll();
        }
    
        @Override
        public void transfer(String fromActno, String toActno, Double money) {
            // 获取转出账户
            Account fromAct = accountMapper.selectByActno(fromActno);
            // 判断余额是否充足
            if (fromAct.getBalance() < money) {
                throw new RuntimeException("余额不足!!!");
            }
            // 获取转入账户
            Account toAct = accountMapper.selectByActno(toActno);
            // 更新内存中账户余额
            fromAct.setBalance(fromAct.getBalance() - money);
            toAct.setBalance(toAct.getBalance() + money);
            // 写入到数据库中
            int count = accountMapper.update(fromAct);
            count += accountMapper.update(toAct);
    
            if (count != 2) {
                throw new RuntimeException("转账失败!!!");
            }
        }
    }
    
    • 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

    为了方便维护,我们将数据源的连接属性独立迟来成为一个配置文件 jdbc.properties

    jdbc.driver = com.mysql.cj.jdbc.Driver
    jdbc.url = jdbc:mysql://localhost:3306/powernode
    # 这里不要直接使用username,因为默认获取的是当前计算机的用户名
    jdbc.username = root
    jdbc.password = 111111
    
    • 1
    • 2
    • 3
    • 4
    • 5

    编写我们MyBatis的核心配置文件,此处我们就做一个设置开启打印日志功能,重要的配置我们直接在spring的配置文件中进行配置

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <!--开启打印日志文件-->
        <settings>
            <setting name="logImpl" value="STDOUT_LOGGING"/>
        </settings>
    </configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    编写我们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">
    
        <!--开启组件扫描 >> 输入scan选定可以自动配置 xmlns:context-->
        <context:component-scan base-package="com.powernode.bank" />
        <!--引入我们的外部文件-->
        <context:property-placeholder location="jdbc.properties" />
        <!--配置我们的德鲁伊连接池-->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <!--连接池需要四个属性-->
            <property name="driverClassName" value="${jdbc.driver}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </bean>
        <!--配置SqlSessionFactoryBean >> 我猜就是类似于SqlSessionFactoryBuilder的功能-->
        <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!--创建会话必然需要数据库连接池-->
            <property name="dataSource" ref="dataSource"/>
            <!--配置mybatis核心配置文件-->
            <property name="configLocation" value="mybatis-config.xml"/>
            <!--批量指定别名 >> 为我们的普通pojo类-->
            <property name="typeAliasesPackage" value="com.powernode.bank.pojo"/>
        </bean>
        <!--配置我们指定要扫描的mapper包 >> 因为我们将mapper接口和对应映射文件已经放到一个包中了-->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <!--指定扫描哪个包-->
            <property name="basePackage" value="com.powernode.bank.mapper"/>
        </bean>
        <!--配置事务管理器-->
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!--事务管理器需要连接数据源-->
            <property name="dataSource" ref="dataSource"/>
        </bean>
        <!--开启事务的注解扫描-->
        <tx:annotation-driven transaction-manager="txManager"/>
    </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

    编写测试程序,因为我们就想看配置是否成功以及能否成功转账,所以我们不配置Springjunit的支持了

    package com.powernode.bank.test;
    
    import com.powernode.bank.service.AccountService;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.lang.reflect.AccessibleObject;
    
    /**
     * @author Bonbons
     * @version 1.0
     */
    public class SMTest {
        @Test
        public void test(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            AccountService accountService = applicationContext.getBean("accountService", AccountService.class);
            accountService.transfer("act-001", "act-002", 1000.0);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    • 通过运行结果我们可以得知 >> 配置成功并成功完成转账操作
      在这里插入图片描述
    • 既然我们添加了事务,那么我们在转账处添加一个异常,测试发生异常是否会回滚
      在这里插入图片描述
    • 通过测试我们可以看到发生了回滚 >> 表中数据没有发生异常变动【如果没有回滚,那么用户1会少1000,但用户2的余额不会增加】

    在这里插入图片描述

    • 补充一个小知识点,就是IDEA中提供了直接操作数据库的插件
      • 点击右侧DataBase,点击+选择数据库
      • 第一次运行需要下载一些文件
      • 然后输入用户名和密码就可以连接到我们的数据库

    三、Spring中的八大模式

    • 简单工厂模式

      • BeanFactorygetBean()方法,通过唯一标识来获取Bean对象
      • 是典型的简单工厂模式是静态工厂模式,但是不属于GoF23种设计模式
    • 工厂方法模式

      • FactoryBean是典型的工厂方法模式
      • 在配置文件中通过factory-method属性来指定工厂方法,该方法是一个实例方法
    • 单例模式

      • Spring用的是双重判断加锁的单例模式
        在这里插入图片描述
    • 代理模式

      • SpringAOP就是使用了动态代理实现的【让其他对象代替完成操作】
    • 装饰器模式

      • JavaSE中的IO流是非常典型的装饰器模式,在尽可能少修改原有类代码下的情况下,做到动态切换
      • Spring中类名中带有:DecoratorWrapper单词的类,都是装饰器模式
    • 观察者模式

      • 定义对象间的一对多的关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新
      • Spring中观察者模式一般用在listener的实现【Spring中的事件编程模型】
    • 策略模式

      • 策略模式是行为性模式,调用不同的方法,适应行为的变化 ,强调父类的调用子类的特性
    • 模板方法模式

      • Spring中的JdbcTemplate类就是一个模板方法设计模式的体现
      • 在模板类的模板方法execute中编写核心算法,具体的实现步骤在子类中完成

    在这里插入图片描述

  • 相关阅读:
    使用虚拟机Ubuntu进行MPI环境搭建
    Unity_Demo | 中世纪风3D-RPG游戏
    轻量自高斯注意力(LSGA)机制
    20个最佳实践提升Terraform工作流程|Part 2
    自动泊车系统设计学习笔记
    微信公众号之微信认证
    【项目】GZIP压缩项目详解 (LZ77+Huffman编码)
    [CM311-1A]-安卓设备视频分辨率 DPI 以及刷新率问题
    Vue+elementUI 导出word打印
    Java笔记【方法、数组】
  • 原文地址:https://blog.csdn.net/qq_61323055/article/details/127939252