spring学习三

本文详细介绍了Spring的单元测试优势,包括避免频繁读取配置文件和简化测试过程,并通过实例演示了如何使用Spring进行单元测试。此外,还深入讲解了Spring的声明式事务管理,包括设置转账环境、配置事务管理器、开启事务注解以及在异常情况下事务的回滚行为,确保操作的原子性。
摘要由CSDN通过智能技术生成
1、spring的单元测试

(1)为什么要用spring的单元测试:
A、应用程序的入口:main方法;
B、junit中没有main方法也能执行,是因为junit中集成了一个main方法,它去判断哪些方法上有对应的@Test注解,然后执行之;
C、但是在junit中,它不会去管我们是否使用spring,所以每次进行测试都要去读取配置文件,创建对象!
(2)比如现在有一个类UserDao,我们要测试它的add方法;
UserDao.java:

package cn.melo.dao;

import org.springframework.stereotype.Component;

@Component(value = "userDao")
public class UserDao {

   public void add(){
       System.out.println("add........");
   }
}

beans.xml中配置注解扫描:

<!--扫描注解-->
<context:component-scan base-package="cn.melo"></context:component-scan>

原始的做法(只用junit):

package cn.melo.test;

import cn.melo.dao.UserDao;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test1 {
    @Test
    public void test1(){
        ApplicationContext context = new
                ClassPathXmlApplicationContext("beans.xml");
        UserDao userDao = context.getBean("userDao", UserDao.class);
        System.out.println(userDao);
        userDao.add();
    }
}

测试结果:
在这里插入图片描述
用spring的单元测试的做法
首先导入junit相关的jar包和spring-test的jar包,然后写测试代码:

package cn.melo.test;

import cn.melo.dao.UserDao;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
//如果创建对象使用的是注解配置,那么就指定注解在哪个类上
@ContextConfiguration(classes = UserDao.class)
//如果创建对象使用的是xml配置,那么就指定xml的位置
//@ContextConfiguration(locations = "classpath:beans.xml")
public class Test {
    @Autowired
    private ApplicationContext context;

    @org.junit.Test
    public void test(){
       UserDao userDao = context.getBean("userDao",UserDao.class);
        System.out.println(userDao);
        userDao.add();
    }
}

测试结果:
在这里插入图片描述
可见用spring的单元测试时,只需要提供一个ApplicationContext类型的属性,再给它加上自动注入的注解,它就会在执行测试方法之前,去加载配置文件;就不用频繁的去读配置文件了,也便于测试人员测试(因为可能他们不知道如何读取spring配置文件)!

2、spring的声明式事务管理

(1)、搭建一个转账环境:
表user1:
在这里插入图片描述
(2)、创建service和dao类完成注入
User1.java

package cn.melo.bean;

import java.io.Serializable;

public class User1 implements Serializable {
    private Integer uid;
    private String uname;
    private Double umoney;

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public Double getUmoney() {
        return umoney;
    }

    public void setUmoney(Double umoney) {
        this.umoney = umoney;
    }

    @Override
    public String toString() {
        return "User1{" +
                "uid=" + uid +
                ", uname='" + uname + '\'' +
                ", umoney=" + umoney +
                '}';
    }
}

user1Dao.java:

package cn.melo.dao;


import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

public class User1Dao {
    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    //转钱的方法
    public void giveMoney(){
        //操作数据库
        //先让Anthony少200元
        String sql = "update user1 set umoney=umoney-? where uid=?";
        jdbcTemplate.update(sql,200,1);
    }
    //收钱的方法
    public void recieveMoney(){
        //再让melo多两百元
        String sql = "update user1 set umoney=umoney+? where uid=?";
        jdbcTemplate.update(sql,200,2);
    }
}

User1Service.java

package cn.melo.service;

import cn.melo.dao.User1Dao;

public class User1Service {
    private User1Dao user1Dao;

    public void setUser1Dao(User1Dao user1Dao) {
        this.user1Dao = user1Dao;
    }

    public void transferAccounts(){
        user1Dao.giveMoney();
        user1Dao.recieveMoney();
    }
}

beans.xml:

<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       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/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
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">

    <!--扫描注解-->
    <context:component-scan base-package="cn.melo"></context:component-scan>

    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql:///mydb?serverTimezone=GMT%2b8&amp;characterEncoding=utf8">
        </property>
        <property name="username" value="root"></property>
        <property name="password" value="123"></property>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="druidDataSource"></property>
    </bean>
    <bean id="user1Dao" class="cn.melo.dao.User1Dao">
    	<property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>
    <bean id="user1Service" class="cn.melo.service.User1Service">
        <property name="user1Dao" ref="user1Dao"></property>
    </bean>

</beans>

测试代码:
Test.java

package cn.melo.test;

import cn.melo.service.User1Service;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:beans.xml")
public class Test {
    @Autowired
    private ApplicationContext context;

    @org.junit.Test
    public void testTransferAccounts(){
        User1Service user1Service = context.getBean("user1Service",User1Service.class);
        user1Service.transferAccounts();
    }
}

测试结果
”
还原user1表,然后在service的两个操作之间中加入一个异常再测试;
在这里插入图片描述
再测试:
在这里插入图片描述
在这里插入图片描述
这是我们不希望看到的,我们希望User1Dao中的两个操作,要么都成功,要么都失败!!

所以,我们就需要事务来管理这两个操作:
配置事务(加上以下的配置):
beans.xml:

<!--配置事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="druidDataSource"></property>
</bean>
<!--配置事务增强-->
<tx:advice id="txadvice" transaction-manager="transactionManager">
    <!--做事务操作-->
    <tx:attributes>
        <!--设置进行事务操作的方法的匹配规则-->
        <!--propagation:事务的传播行为-->
        <!--isolation:事务的隔离级别-->
        <tx:method name="transferAccounts" propagation="REQUIRED" isolation="REPEATABLE_READ" read-only="false"/>
    </tx:attributes>
</tx:advice>

<!--配置切面-->
<aop:config>
    <!--切入点-->
    <aop:pointcut id="pointcut1" expression="execution(* cn.melo.service.User1Service.*(..))"/>
    <!--切面-->
    <aop:advisor advice-ref="txadvice" pointcut-ref="pointcut1"></aop:advisor>
</aop:config>

不加异常的情况下测试,没有问题,可以成功转账;
加入异常后,出现回滚!!!

(3)用注解完成事务的配置:
分三步:
第一步:配置事务管理器:
beans.xml:

<!--配置事务管理器-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="druidDataSource"></property>
</bean>

第二步:开启事务注解:
beans.xml

<!--开启事务注解-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>

第三步,在要进行事务处理的类上加上注解:@Transactional
在这里插入图片描述
分别进行有无异常的测试都可以成功,表明OK!!!

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值