Spring框架学习总结

根据动力节点的视频学习后做出的一点总结

2020最新Spring框架教程【IDEA版】-Spring框架从入门到精通_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1nz4y1d7uy?p=102

Spring框架

Spring 是于 2003 年兴起的一个轻量级的 Java 开发框架,它是为了解决企业应用开发 的复杂性而创建的。Spring 的核心是控制反转(IoC)和面向切面编程(AOP)。Spring 是可以在 Java SE/EE 中使用的轻量级开源框架。

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

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

IoC 控制反转

        控制反转(IoC,Inversion of Control),是一个概念,是一种思想。指将传统上由程序代码直接操控的对象调用权交给容器,通过容器来实现对象的装配和管理。控制反转就是对对象控制权的转移,从程序代码本身反转到了外部容器。通过容器实现对象的创建,属性赋值,依赖的管理。

        依赖注入:DI(Dependency Injection),程序代码不做定位查询,这些工作由容器自行 完成。

        Spring 框架使用依赖注入(DI)实现 IoC。 Spring 容器是一个超级大工厂,负责创建、管理所有的 Java 对象,这些 Java 对象被称 为 Bean。Spring 容器管理着容器中 Bean 之间的依赖关系,Spring 使用“依赖注入”的方式 来管理 Bean 之间的依赖关系。使用 IoC 实现对象之间的解耦和。

        注入有三种方式:set注入,构造注入和使用注解注入.  set注入和构造注入在spring文件里面,使用注解注入在实体类里面.

在实际使用中,系统中的Bean数量多时可以将Spring配置文件分解成多个配置文件,多个配置文件中有一个总文件,总配置文件将各其它子文件通过引入。在 Java 代码中只需要使用总配置文件对容器进行初始化即可。例如:

Spring框架学习总结_第1张图片

Spring 配置文件:

         也可使用通配符*。但此时要求父配置文件名不能满足*所能匹配的格式,否则将出现循环递归包含。就本例而言,父配置文件不能匹配 spring-*.xml 的格式,即不能起名为 spring-total.xml。Spring框架学习总结_第2张图片

使用步骤

Spring框架学习总结_第3张图片

基本目录如下图

Spring框架学习总结_第4张图片

操作数据库的是上面domain里面的

1.在pom.xml中引入依赖

2.定义接口与实体类

 
  

Student类

package service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * * @Component 创建对象的,等同于  的功能
 *      属性:value 就是对象的名称,技师bean的id value的值是唯一的,在整个spring容器中就一个
 *      位置:在类的上面
 *      value=""可以省略
 *      也可以省略value及内容,不指定对象名称,由spring提供默认名称:类名的首字母小写
 * *        @Component() 与 @Component(value = "student")相同
 * * @Repository : 放在dao的实现类上面,表示创建dao对象
 * * @Service : 放在service的实现类上面,创建service对象
 * * @Controller : 放在控制器类的上面,创建控制器的对象(Servlet)
 *   以上三个注解的使用语法和@Component一样,都能创建对象,但是这三个注解还有额外功能
 *
 */
@Component(value = "myStudent")
public class Student {
    /**
     * * @Value: 简单类型的属性赋值
     *      属性: value是String类型的,表示简单类型的属性值
     *      位置: 1.在属性定义的上面,无需set,推荐使用
     *           2.在set方法的上面(调用的set方法)
     */
    @Value(value = "张三三")
    private String name;
    @Value("20")
    private int age;
    //声明一个引用类型
    /**引用类型
     * * @Autowired : spring框架提供的注解,实现引用类型的赋值.
     *      spring中通过注解给引用类型赋值,使用的是自动注入原理,byName和byType都支持
     *      默认使用的是byType自动注入
     *
     *      属性:
     *          required,是一个boolean类型的,默认是true
     *          表示引用类型赋值失败后的操作
     *              true:程序报错,并中止执行
     *              false:程序不报错,将null赋给对应的值
     *
     *      位置:1.在属性定义的上面,无需set方法,推荐使用
     *          2.在set方法的上面
     *      如果要使用byName的方式,需要做的是:
     *          1.在属性上面加入@Autowired
     *          2.在属性上面加入@Qualifier(value="bean的id"):表示指定名称的完成赋值
     *          这两个不分先后顺序
     * * @Resource : 来自jdk中的注解,spring框架提供了对这个注解的功能支持,可以使用它给引用类型赋值
     *               使用的也是自动注入原理,支持byName,byType,默认是byName
     *               先使用byName自动注入,如果byName失败,然后采用byType
     */
//    @Autowired()
//    @Qualifier("mySchool")
//    @Autowired(required = false)
//    @Qualifier("mySchool1")
    private School school;

    public Student() {
    }

    public Student(String name, int age, School school) {
        this.name = name;
        this.age = age;
        this.school = school;
    }

    public void setSchool(School school) {
        this.school = school;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school=" + school +
                '}';
    }
}

School类


package service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("mySchool")
public class School {
    @Value("蓝翔++")
    private String name;
    @Value("不知道")
    private String address;

    public School() {
    }

    public School(String name, String address) {
        this.name = name;
        this.address = address;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

3.创建spring配置文件

        在resources目录中创建一个xml文件,文件名建议applicationContext.xml

下面为applicationContext01.xml




    
    
    
    
    
    
    
    
        
        
        
        
    
    
    
        
        
    

    
    
    
        
        
        
    
    
        
        
        
        
    
    
        
        
    

    
    
        
        
    

    
    
    
        
        
    
    
        
        
    
    
    
    









4.测试

package org.example;

import static org.junit.Assert.assertTrue;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.SomeService;
import service.Student;

import java.io.*;
import java.util.Date;

/**
 * Unit test for simple App.
 */
public class AppTest {
    /*
        spring默认创建对象的时间:在创建spring的容器时,会创建配置文件中的所有对象.
        spring创建对象,默认调用的是无参数构造方法
     */
    @Test
    public void test01(){
        //使用spring容器创建对象
        //1.指定spring配置文件的名称
        String config = "applicationContext01.xml";
        //2.创建表示spring容器的对象,ApplicationContext
        //ApplicationContext就是表示spring容器,通过容器获取其中的对象
        //ClassPathXmlApplicationContext:表示从类路径中加载spring的配置文件
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        //从容器中获取某个对象 getBean("配置文件中的bean的id值");
        SomeService service = (SomeService) ac.getBean("someService");
        //使用spring创建好的对象
        service.doSome("zs",20);

        //构造方法中的输出语句先于上个对象的普通方法执行
        SomeService service1 = (SomeService) ac.getBean("someService1");
    }

    /**
     * 获取spring容器中java对象的信息
     */
    @Test
    public void test02(){
        String config = "applicationContext01.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        //获取容器中定义对象的数量
        int number = ac.getBeanDefinitionCount();
        System.out.println("容器中定义的对象的数量为:"+number);
        //容器中每个定义的对象的名称
        String[] names = ac.getBeanDefinitionNames();
        for (String name:names){
            System.out.println(name);
        }
    }

    //获取一个非自定义类的对象
    @Test
    public void test03() {
        String config = "applicationContext01.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        Date date = (Date) ac.getBean("myDate");
        System.out.println(date);
    }

    //set注入
    @Test
    public void test04(){
        String config = "applicationContext01.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        Student student = (Student) ac.getBean("myStudent");
        System.out.println(student);
    }

    //构造注入
    @Test
    public void test05(){
        String config = "applicationContext01.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        //使用构造注入 name
//        Student student = (Student) ac.getBean("myStudentCon");
        //使用构造注入 index
        Student student = (Student) ac.getBean("myStudentCon2");
        System.out.println(student);
    }

    //构造注入创建File
    @Test
    public void test06() throws IOException {
        String config = "applicationContext01.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        File file = (File) ac.getBean("myFile");
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
        String s;
        while ((s=br.readLine())!=null){
            System.out.println(s);
        }
    }

    //自动注入
    @Test
    public void test07(){
        String config = "applicationContext01.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        //byName
//        Student student = (Student) ac.getBean("studentAutoByName");
        //byType
        Student student = (Student) ac.getBean("studentAutoByType");
        System.out.println(student);
    }

    //注解获取对象,赋值
    @Test
    public void test08(){
        String config = "applicationContext02.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        Student student = (Student) ac.getBean("myStudent");
        System.out.println(student);
    }
}

Spring 集成 MyBatis

        将 MyBatis 与 Spring 进行整合,主要解决的问题就是将 SqlSessionFactory 对象交由 Spring 来管理。所以,该整合,只需要将 SqlSessionFactory 的对象生成器 SqlSessionFactoryBean 注册在 Spring 容器中,再将其注入给 Dao 的实现类即可完成整合。

        实现 Spring 与 MyBatis 的整合常用的方式:扫描的 Mapper 动态代理

实现

Spring框架学习总结_第5张图片

1.添加依赖pom.xml

2.定义实体类

package domain;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

public class Student {

    private Integer SNO;
    private String SNAME;
    private String SSEX;
    private String SDEPT;

    public Student(Integer SNO, String SNAME, String SSEX, String SDEPT) {
        this.SNO = SNO;
        this.SNAME = SNAME;
        this.SSEX = SSEX;
        this.SDEPT = SDEPT;
    }

    public Student() {
    }

    public Integer getSNO() {
        return SNO;
    }

    public void setSNO(Integer SNO) {
        this.SNO = SNO;
    }

    public String getSNAME() {
        return SNAME;
    }

    public void setSNAME(String SNAME) {
        this.SNAME = SNAME;
    }

    public String getSSEX() {
        return SSEX;
    }

    public void setSSEX(String SSEX) {
        this.SSEX = SSEX;
    }

    public String getSDEPT() {
        return SDEPT;
    }

    public void setSDEPT(String SDEPT) {
        this.SDEPT = SDEPT;
    }

    @Override
    public String toString() {
        return "domain.Student{" +
                "SNO=" + SNO +
                ", SNAME='" + SNAME + '\'' +
                ", SSEX='" + SSEX + '\'' +
                ", SDEPT='" + SDEPT + '\'' +
                '}';
    }
}

3.定义StudentDao接口和映射文件mapper(命名与接口名相同)

        mapper 中的 namespace 取值也为 Dao 接口的全限定性名。

package dao;

import service.Student;
import java.util.List;

public interface StudentDao {
    int insertStudent(Student student);
    List selectAllStudents();
}



    
        insert into Student (Sno,Sname,Ssex,Sdept) values (#{SNO},#{SNAME},#{SSEX},#{SDEPT})
    

    
    
    
        select SNO,SNAME,SSEX,SDEPT from Student
    

4.定义Service接口和实现类

package service;

public interface SomeService {
    void doSome(String name,Integer age);
    String doOther(String name,Integer age);
    String doAround(String name, Integer age);
    void doAfterThrowing();
    void doAfter();
}
package service.impl;

import dao.StudentDao;
import service.Student;
import service.StudentService;

import java.util.List;

public class StudentServiceImpl implements StudentService {

    //引用类型
    private StudentDao studentDao;

    //使用set注入,赋值
    public void setStudentDao(StudentDao studentDao){
        this.studentDao = studentDao;
    }

    @Override
    public int addStudent(Student student) {
        return studentDao.insertStudent(student);
    }

    @Override
    public List queryStudents() {
        return studentDao.selectAllStudents();
    }
}

5.定义Mybatis主配置文件





    
    
        
        
    

    
    
        
        
    

    
    
        
    

    
    
        
        
        
        
    

6.定义Spring配置文件




    
    

    
    

        
        
        
        
        
        
    

    
    
        
        

        

    

    
    
        
        
        
        
    

    
    
        
    

jdbc.properties

jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:orcl
jdbc.user=system
jdbc.password=password

测试

package org.example;

import dao.StudentDao;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.Student;
import service.StudentService;

import java.util.List;

public class AppTest03 {
    @Test
    public void test01(){
        String config = "applicationContext03.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        String[] names  = ac.getBeanDefinitionNames();
        for (String s:names)
            System.out.println("容器中对象名称"+s);
    }
    @Test
    public void test02(){
        String config = "applicationContext03.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        StudentDao studentDao = (StudentDao) ac.getBean("studentDao");
        List students = studentDao.selectAllStudents();
        students.forEach(student -> System.out.println(student));
    }
    @Test
    public void test03(){
        String config = "applicationContext03.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        StudentService service = (StudentService) ac.getBean("studentService");
        List students = service.queryStudents();
        students.forEach(student -> System.out.println(student));
    }
}

Spring 事务处理

        事务是指一组sql语句的集合, 集合中有多条sql语句,可能是insert , update ,select ,delete, 我们希望这些多个sql语句都能成功,或者都失败, 这些sql语句的执行是一致的,作为一个整体执行。

        事务原本是数据库中的概念,在 Dao 层。但一般情况下,需要将事务提升到业务层, 即 Service 层。这样做是为了能够使用事务的特性来管理具体的业务。

在 Spring 中通常可以通过以下两种方式来实现对事务的管理:

        (1)使用 Spring 的事务注解管理事务 (2)使用 AspectJ 的 AOP 配置管理事务

事务管理器接口

        事务管理器是 PlatformTransactionManager 接口对象。其主要用于完成事务的提交、回滚,及获取事务的状态信息。

Spring框架学习总结_第6张图片

 常用的两个实现类

 PlatformTransactionManager 接口有两个常用的实现类:

        ➢ DataSourceTransactionManager:使用 JDBC 或 MyBatis 进行数据库操作时使用。

        ➢ HibernateTransactionManager:使用 Hibernate 进行持久化数据时使用。

Spring的回滚方式

        Spring 事务的默认回滚方式是:发生运行时异常和 error 时回滚,发生受查(编译)异常时 提交。不过,对于受查异常,程序员也可以手工设置其回滚方式。

事务定义接口

        事务定义接口 TransactionDefinition 中定义了事务描述相关的三类常量:事务隔离级别、 事务传播行为、事务默认超时时限,及对它们的操作。

Spring框架学习总结_第7张图片

 Spring框架学习总结_第8张图片

 Spring框架学习总结_第9张图片

Spring框架学习总结_第10张图片

定义了五个事务隔离级别常量

这些常量均是以 ISOLATION_开头。即形如 ISOLATION_XXX。

        ➢ DEFAULT:采用 DB 默认的事务隔离级别。MySql 的默认为 REPEATABLE_READ; Oracle 默认为 READ_COMMITTED。

        ➢ READ_UNCOMMITTED:读未提交。未解决任何并发问题。

        ➢ READ_COMMITTED:读已提交。解决脏读,存在不可重复读与幻读。

        ➢ REPEATABLE_READ:可重复读。解决脏读、不可重复读,存在幻读

        ➢ SERIALIZABLE:串行化。不存在并发问题。

定义了七个事务传播行为常量

        所谓事务传播行为是指,处于不同事务中的方法在相互调用时,执行期间事务的维护情 况。如,A 事务中的方法 doSome()调用 B 事务中的方法 doOther(),在调用执行期间事务的 维护情况,就称为事务传播行为。

        事务传播行为是加在方法上的。 事务传播行为常量都是以 PROPAGATION_ 开头,形如 PROPAGATION_XXX。

PROPAGATION_REQUIRED

        指定的方法必须在事务内执行。若当前存在事务,就加入到当前事务中;若当前没有事 务,则创建一个新事务。这种传播行为是最常见的选择,也是 Spring 默认的事务传播行为。

        如该传播行为加在 doOther()方法上。若 doSome()方法在调用 doOther()方法时就是在事 务内运行的,则 doOther()方法的执行也加入到该事务内执行。若 doSome()方法在调用 doOther()方法时没有在事务内执行,则 doOther()方法会创建一个事务,并在其中执行。

Spring框架学习总结_第11张图片

PROPAGATION_REQUIRES_NEW

        指定的方法支持当前事务,但若当前没有事务,也可以以非事务方式执行。

Spring框架学习总结_第12张图片

PROPAGATION_SUPPORTS

        总是新建一个事务,若当前存在事务,就将当前事务挂起,直到新事务执行完毕。

Spring框架学习总结_第13张图片

PROPAGATION_MANDATORY

PROPAGATION_NESTED

PROPAGATION_NEVER

PROPAGATION_NOT_SUPPORTED

定义了默认事务超时时限

        常量 TIMEOUT_DEFAULT 定义了事务底层默认的超时时限,sql 语句的执行时长。

         注意,事务的超时时限起作用的条件比较多,且超时的时间计算点较复杂。所以,该值一般使用默认值即可。

实现

1.创建数据库表

2.添加依赖pom.xml

3.创建实体类

package domain;

public class Goods {
    private String GNAME;
    private Integer GCOST;
    private Integer GNUMBER;
    private final String MARK = "";

    public Goods() {
    }

    public Goods(String GName, Integer GCost, Integer GNumber) {
        this.GNAME = GName;
        this.GCOST = GCost;
        this.GNUMBER = GNumber;
    }

    public void setGNAME(String GNAME) {
        this.GNAME = GNAME;
    }

    public void setGCOST(Integer GCOST) {
        this.GCOST = GCOST;
    }

    public void setGNUMBER(Integer GNUMBER) {
        this.GNUMBER = GNUMBER;
    }

    public Integer getGNUMBER() {
        return GNUMBER;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "GName='" + GNAME + '\'' +
                ", GCost=" + GCOST +
                ", GNumber=" + GNUMBER +
                '}';
    }
}
package domain;

public class Sale {
    private String NAME;
    private Integer NUMS;

    public Sale(String name, Integer nums) {
        this.NAME = name;
        this.NUMS = nums;
    }

    public void setNAME(String NAME) {
        this.NAME = NAME;
    }

    public void setNUMS(Integer NUMS) {
        this.NUMS = NUMS;
    }
}

4.定义Dao接口和mapper映射文件

package dao;

import domain.Goods;

import java.util.List;

public interface GoodsDao {
    int insertStudent(Goods goods);
    int updateGoodNumber(Goods goods);
    int updateGoodCost(Goods goods);
    Goods selectGood(String name);
    List selectAllGoods();
}




    
        insert into GOODS (GNAME,GCOST,GNUMBER,MARK)
        values (#{GNAME}, #{GCOST}, #{GNUMBER}, #{MARK})
    

    
        update GOODS set GNUMBER = GNUMBER - #{GNUMBER} where GNAME = #{GNAME}
    

    
        update GOODS set GCOST = #{GCOST} where GNAME = #{GNAME}
    

    

    


package dao;

import domain.Sale;

public interface SaleDao {
    int insertSale(Sale sale);
}



    
        insert into SALE (NAME,NUMS)
        values (#{NAME}, #{NUMS})
    

5.定义异常类

package service.excep;

//自定义的运行时异常类
public class NotEnoughException extends RuntimeException{
    public NotEnoughException() {
        super();
    }

    public NotEnoughException(String message) {
        super(message);
    }
}

6.定义Service接口和实现类

package service;

public interface BuyGoodsService {
    int buy(String GName, Integer GNumber);
    void selectAllGoods();
}
package service.impl;

import dao.GoodsDao;
import dao.SaleDao;
import domain.Goods;
import domain.Sale;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import service.BuyGoodsService;
import service.excep.NotEnoughException;

import java.util.List;

public class BuyGoodsServiceImpl implements BuyGoodsService {
    private SaleDao saleDao;
    private GoodsDao goodsDao;

    /**第一种方法
     * 一般使用默认值,只在上面加一个@Transactional即可
     * rollbackFor:表示发生指定的异常一定回滚
     *  处理逻辑是:
     *  1)spring框架会首先检查方法抛出的异常是不是在rollbackFor的属性值中,
     *  如果异常在rollbackFor列表中,不管是什么类型的异常,一定回滚
     *  2)如果抛出的异常不在rollbackFor列表中,spring会判断异常是不是RuntimeException
     *  如果是则回滚
     */
//    @Transactional(
//            propagation = Propagation.REQUIRED,
//            isolation = Isolation.DEFAULT,
//            readOnly = false,
//            rollbackFor = {
//                    NullPointerException.class,NotEnoughException.class
//            }
//    )
    @Override
    public int buy(String name, Integer number) {
        System.out.println("=====buy方法开始=====");
        //记录销售信息,向sale表中添加记录
        int n = saleDao.insertSale(new Sale(name, number));

        Goods goods = goodsDao.selectGood(name);
        if (goods==null)
            throw new NullPointerException(name + "商品不存在");
        else if (goods.getGNUMBER()<0)
            throw new NotEnoughException(name + "商品库存不足");
        //更新库存
        Goods buyGoods = new Goods();
        buyGoods.setGNAME(name);
        buyGoods.setGNUMBER(number);
        goodsDao.updateGoodNumber(buyGoods);
        System.out.println("=====buy方法结束=====");
        return n;
    }

    @Override
    public void selectAllGoods() {
        List goods = goodsDao.selectAllGoods();
        if (goods==null)
            throw new NullPointerException("商品不存在!");
    }

    public void setSaleDao(SaleDao saleDao) {
        this.saleDao = saleDao;
    }

    public void setGoodsDao(GoodsDao goodsDao) {
        this.goodsDao = goodsDao;
    }

}

7.Mybatis文件





    
    
        
        
    

    
    
        
        
    

    
    
        
    

    
    
        
        
        
        
    

8.修改Spring配置文件内容




    
    

    
    
        
        
        
        
        
        
    

    
    
        
        

        
        
    

    
    
        
        
        
        
    

    
    
        
        
    

    
    
    
        
        
    

    





    
    
    
        
        
            
            
            




        
    
    
    
        
        
        
        
    

jdbc.properties

jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:orcl
jdbc.user=system
jdbc.password=password

测试

package org.example;

import dao.GoodsDao;
import domain.Goods;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.BuyGoodsService;

import java.util.List;

public class Apptest04 {
    @Test
    public void test01(){
        String config = "applicationContext04.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        GoodsDao goodsDao = (GoodsDao) ac.getBean("goodsDao");
        List goods = goodsDao.selectAllGoods();
        goods.forEach(goods1 -> System.out.println(goods1));
    }
    @Test
    public void test02(){
        String config = "applicationContext04.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        GoodsDao goodsDao = (GoodsDao) ac.getBean("goodsDao");
        int num = goodsDao.insertStudent(new Goods("钢笔",50,300));
        System.out.println("插入了"+num+"条数据");
    }

    @Test
    public void test03(){
        String config = "applicationContext04.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        GoodsDao goodsDao = (GoodsDao) ac.getBean("goodsDao");
        Goods goods = new Goods();
        goods.setGNAME("钢笔");
        goods.setGNUMBER(10);
        int num = goodsDao.updateGoodNumber(goods);
        System.out.println("更新了"+num+"条数据");
    }

    @Test
    public void test04(){
        String config = "applicationContext04.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        BuyGoodsService buyGoodsService = (BuyGoodsService) ac.getBean("buyGoodsService");
        int num = buyGoodsService.buy("钢笔",10);
        System.out.println("更新了"+num+"条数据");
    }
}

使用 Spring 的事务注解管理事务

        通过@Transactional 注解方式,可将事务织入到相应 public 方法中,实现事务管理。 @Transactional 的所有可选属性如下所示:

                ➢ propagation:用于设置事务传播属性。该属性类型为 Propagation 枚举,默认值为Propagation.REQUIRED。

                ➢ isolation:用于设置事务的隔离级别。该属性类型为 Isolation 枚举,默认值为 Isolation.DEFAULT。

                ➢ readOnly:用于设置该方法对数据库的操作是否是只读的。该属性为 boolean,默认值 为 false。

                ➢ timeout:用于设置本操作与数据库连接的超时时限。单位为秒,类型为 int,默认值为 -1,即没有时限。

                ➢ rollbackFor:指定需要回滚的异常类。类型为 Class[],默认值为空数组。当然,若只有 一个异常类时,可以不使用数组。

                ➢ rollbackForClassName:指定需要回滚的异常类类名。类型为 String[],默认值为空数组。 当然,若只有一个异常类时,可以不使用数组。

                ➢ noRollbackFor:指定不需要回滚的异常类。类型为 Class[],默认值为空数组。当然,若 只有一个异常类时,可以不使用数组。

                ➢ noRollbackForClassName:指定不需要回滚的异常类类名。类型为 String[],默认值为空 数组。当然,若只有一个异常类时,可以不使用数组。

        需要注意的是,@Transactional 若用在方法上,只能用于 public 方法上。对于其他非 public 方法,如果加上了注解@Transactional,虽然 Spring 不会报错,但不会将指定事务织入到该 方法中。因为 Spring 会忽略掉所有非 public 方法上的@Transaction 注解。

         若@Transaction 注解在类上,则表示该类上所有的方法均将在执行时织入事务。

 实现注解的事务步骤:

1.声明事务管理器

2.开启注解驱动

Spring框架学习总结_第14张图片

3.业务层public方法加入事务属性

Spring框架学习总结_第15张图片

 使用 AspectJ 的 AOP 配置管理事务

        使用 XML 配置事务代理的方式的不足是,每个目标类都需要配置事务代理。当目标类 较多,配置文件会变得非常臃肿。

        使用 XML 配置顾问方式可以自动为每个符合切入点表达式的类生成事务代理。其用法很简单,只需将前面代码中关于事务代理的配置删除,再替换为如下内容即可。

1.加入依赖

Spring框架学习总结_第16张图片

2.在容器中添加事务管理器

3.配置事务通知

Spring框架学习总结_第17张图片

4.配置增强器

Spring框架学习总结_第18张图片

5.修改测试类

Spring框架学习总结_第19张图片

Spring配置Web项目

        在 Web 项目中使用 Spring 框架,首先要解决在 web 层(这里指 Servlet)中获取到 Spring 容器的问题。只要在 web 层获取到了 Spring 容器,便可从容器中获取到 Service 对象。

实现

将 spring-test项目中内容复制到当前项目中:

1.Service 层、Dao 层代码

2.配置文件 applicationContext.xml 及 jdbc.properties,mybatis.xml

3.pom.xml

4.加入 servlet ,jsp 依赖

5.定义index页面

<%@ page contentType="text/html;charset=utf-8" language="java" %>


    Title


    

注册学生

学号:
姓名:
性别:
学院:

6.定义RegisterServlet

package controller;

import domain.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import service.StudentService;

import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class RegisterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String id = req.getParameter("id");
        String name = req.getParameter("name");
        String sex = req.getParameter("sex");
        String dept = req.getParameter("dept");

        //每次请求都需要新建一个对象,不合适
//        String config = "applicationContext.xml";
//        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        WebApplicationContext ac = null;

        //第一种
        //使用ServletContext中的容器对象,创建好的容器对象
//        String key = WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE;
//        Object attr = getServletContext().getAttribute(key);
//        if (attr!=null){
//            ac = (WebApplicationContext) attr;
//        }

        //第二种
        //使用框架中的方法,获取容器对象
        ServletContext sc = getServletContext();
        ac = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);

        StudentService service = (StudentService) ac.getBean("studentService");
        Student student = new Student(Integer.valueOf(id),name,sex,dept);
        service.insertStudent(student);

        req.getRequestDispatcher("/result.jsp").forward(req,resp);
    }
}

7.定义success页面

<%--
  Created by IntelliJ IDEA.
  User: lenovo
  Date: 2022/1/26
  Time: 18:12
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    注册成功


注册成功

8.web.xml注册Servlet




    
        registerServlet
        controller.RegisterServlet
    
    
        registerServlet
        /register
    

    
    
        contextConfigLocation
        classpath:applicationContext.xml
    
    
        org.springframework.web.context.ContextLoaderListener
    

你可能感兴趣的