Spring框架详解

简介

Spring5框架

内容介绍:

1.Spring概念

2.IOC容器

3.Aop

4.JDBCTEmplate

5.事物管理

6.Spring5新特性



一.Spring框架概述


1.概述


1.Spring框架是轻量级的JavaEE框架

2.Spring可以解决企业应用开发的复杂性

3.Spring有两个核心部分:IOC和Aop

(1)IOC:控制反转,把创建对象的过程交给Spring进行管理

(2)Aop:面向切面,不修改源代码进行功能增强

4.Spring特点

(1)方便解耦,简化开发

(2)Aop变成支持

(3)方便程序测试

(4)方便和其他框架进行整合

(5)方便进行事物操作

(6)降低API开发难度

5.Spring5



2.入门案例

(1)下载spring

image-20220314143447272

image-20220314143522845

image-20220314143622695

image-20220314144841240

image-20220314144949337

最后是这个网址

https://repo.spring.io/ui/native/release/org/springframework/spring/

image-20220314150504340

下载解压

image-20220314151754577

(2)创建新的项目

(3)导入jar包

image-20220314153934649

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SWSNjI6C-1649754754216)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220314212314473.png)]

把所需的jar包导入其中

导入流程:

在项目文件夹中建立lab文件夹

把jar包放入文件夹中

image-20220314213114546

image-20220314213129097

(4)创建普通类

在这个类中创建普通方法

(5)创建Spring配置文件

在配置文件中配置创建的对象

1.Spring配置文件使用xml文件格式

(6)测试代码编写

二.IOC容器

1.IOC底层原理

(1)什么是IOC

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

one:控制反转,把对象的创建和对象的调用过程交给Spring进行管理

two:使用IOC的目的:为了耦合度降低

three:做入门案例就是IOC的实现

(2)IOC底层原理

(1)xml解析,工厂模式,反射

(3)画图讲解IOC底层原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SDr4j6ah-1649754754217)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220316111726329.png)]

IOC过程

(1)配置xml文件,配置创建的对象

image-20220316112411751

(2)有service类和dao类,创建工厂类

image-20220316112721282


2.IOC接口(BeanFactory)

1.IOC思想基于IOC容器完成,IOC容器底层就是对象工厂

2.Spring提供IOC容器实现的两种方式:(两个接口

(1)BeanFactory:

IOC容器中最基本实现方式,时Spring内部使用的接口,不提供开发人员进行使用

**特点:**加载配置文件的时候不会去创建对象,在获取对象(使用)才会去创建对象

(2)ApplicationContext:

BeanFactory接口的子接口,提供更多更强大的功能,一般有开发人员进行使用

**特点:**加载配置文件时候就会把在配置文件的对象进行创建

3.ApplicationContext接口有实现类

image-20220316114527826

FlieSystemXmlApplicationContext对应电脑的盘符路径

ClassPathXmlApplicationContext类路径


3.IOC操作Bean管理(基于xml)

(1)Bean管理定义:

Bean管理指的是两个操作

1.Spring创建对象

2.Spring注入属性

(2)Bean管理操作的两种方式

1.基于xml方式创建对象

2.基于注解方式的实现

1.基于xml配置文件方式的实现


    

(1)在Spring中使用bean标签,在标签里面添加对应的属性,就可以实现对象的创建

(2)在bean标签中有许多的属性,介绍常用的属性

*id属性:唯一标识

*class属性:类全路径(包类路径)

*name属性:和id一样,但是在name中可以加入些特殊符号

(3)创建对象的时候,默认是执行无参数构造方法

2.基于xml方式注入属性

(1)DI:依赖注入,就是注入属性

3.第一种注入方式:使用set方法进行注入

(1)创建类,定义属性和对应的set方法

image-20220316194248500

(2)在Spring配置文件配置对象的创建,配置属性注入

image-20220316194814737

最后测试:

image-20220316202247204

image-20220316202302048

4.第二种注入方式:通过有参构造注入

(1)创建类,定义属性,创建属性对应有参数构造方法

image-20220316202928176

(2)在Spring文件中进行配置

image-20220316204015005

测试:
image-20220316204429603

5.p名称空间注入(了解)

(1)使用P名称空间注入,可以简化基于xml配置方式

第一步:添加p名称空间在配置文件中

image-20220316204924233

第二步:进行属性注入,在bean标签里面进行操作

image-20220316205240433

测试:
image-20220316205335414

(3)IOC操作Bean管理(xml注入其他类型的操作)

字面量

one:null值

eg:
image-20220316220057058

image-20220316220409873

测试:

image-20220316220632665

two:属性值包含特殊符号
1.把<>进行转义<>

image-20220316222400727

2.把带特殊符号内容写到CDATA

image-20220316222546173

测试:(两个的输出结果都一样)

image-20220316222636720

three:注入属性-外部bean

1.创建两个类service和dao类

2.在service调用dao里面的方法

3.在Spring配置文件中进行配置

image-20220317192720503

image-20220317192736845

image-20220317192744546

测试:
image-20220317192825321

four:注入属性-内部bean
  1. 一对多关系:部门和员工

    一个部门有多个员工,一个员工属于一个部门

    部门是一,员工是多

  2. 在实体类之间表示一对多的关系,员工表示所属部门,使用对象类型属性进行表示

  3. 在Spring的配置文件中进行配置

image-20220317195858214

image-20220317195915061

image-20220317195933962

测试:

image-20220317200150961

five:注入属性-级联赋值

1.第一种写法

image-20220317201958522

image-20220317202007299

image-20220317202029413

测试:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SceNe7Ei-1649754754226)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220317202126805.png)]

2.第二种写法

Dept.java

Testbean.java同上

image-20220317202252115

image-20220317202303036

测试:
image-20220317202334223


(4)IOC操作Bean管理(xml注入集合属性)

  1. 注入数组类型属性

  2. 注入List集合类型属性

  3. 注入Map集合类型属性

1.创建类

定义数组,List,Map,Set类型的属性,生成对应的set方法

image-20220317205936079

package com.spring.collectiontype;

import java.nio.MappedByteBuffer;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author yanchaochao
 * @date 2022/3/17 20:34
 */
public class Stu {
    //1.数组类型
    private String[] courses;

    //2.list集合类型属性
    private List list;

    //3.创建Map集合属性
    private Map maps;

    //4.set集合类型
    private Set sets;



    public void setCourses(String[] courses) {
        this.courses = courses;
    }

    public void setList(List list) {
        this.list = list;
    }

    public void setMaps(Map maps) {
        this.maps = maps;
    }

    public void setSets(Set sets) {
        this.sets = sets;

    }

    //测试
    public void test(){
        System.out.println(Arrays.toString(courses));
        System.out.println(list);
        System.out.println(maps);
        System.out.println(sets);
    }
}
2.在spring配置文件进行配置




        
        

                
                
                        
                                java
                                c
                                c++
                                算法
                                mysql
                        
                

                
                
                        
                                张三
                                小三
                        
                

                
                
                        
                                
                                
                        
                

                
                
                       
                               MySQL
                               Redis
                       
                
        

测试:

image-20220317213049666

package com.spring.testdemo;

import com.spring.collectiontype.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author yanchaochao
 * @date 2022/3/17 21:19
 */
public class Testcollectiontype {
    @Test
    public void testCollection(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        Stu stu = context.getBean("stu", Stu.class);
        stu.test();

    }
}
3.在集合里设置对象类型值

        
                
        
        
                
        



 
                
                        
                                
                                
                        
                


Course.java


package com.spring.collectiontype;

/**
 * @author yanchaochao
 * @date 2022/3/17 21:40
 */
public class Course {
    private  String cname;//课程名称

    public void setCname(String cname) {
        this.cname = cname;
    }

    @Override
    public String toString() {
        return "Course{" +
                "cname='" + cname + ''' +
                '}';
    }
}



Stu.java


package com.spring.collectiontype;

import java.nio.MappedByteBuffer;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author yanchaochao
 * @date 2022/3/17 20:34
 */
public class Stu {
    //1.数组类型
    private String[] courses;

    //2.list集合类型属性
    private List list;

    //3.创建Map集合属性
    private Map maps;

    //4.set集合类型
    private Set sets;

    //学生所学多门课程
    private ListcourseList;
    public void setCourseList(List courseList) {
        this.courseList = courseList;
    }

    public void setCourses(String[] courses) {
        this.courses = courses;
    }

    public void setList(List list) {
        this.list = list;
    }

    public void setMaps(Map maps) {
        this.maps = maps;
    }

    public void setSets(Set sets) {
        this.sets = sets;

    }

    //测试
    public void test(){
        System.out.println(Arrays.toString(courses));
        System.out.println(list);
        System.out.println(maps);
        System.out.println(sets);
        System.out.println(courseList);
    }
}


bean1.xml





        
        

                
                
                        
                                java
                                c
                                c++
                                算法
                                mysql
                        
                

                
                
                        
                                张三
                                小三
                        
                

                
                
                        
                                
                                
                        
                

                
                
                       
                               MySQL
                               Redis
                       
                

                
                
                        
                                
                                
                        
                
        
        
        
                
        
        
                
        



Testcollectiontype.java


package com.spring.testdemo;

import com.spring.collectiontype.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author yanchaochao
 * @date 2022/3/17 21:19
 */
public class Testcollectiontype {
    @Test
    public void testCollection(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        Stu stu = context.getBean("stu", Stu.class);
        stu.test();

    }
}

测试:

image-20220317215214058

4.把集合注入的部分提取出来

(1)在spring配置文件中引入名称空间util

(2)使用util标签完成list集合注入提取

Book.java


package com.spring.collectiontype;
import java.util.List;
/**
 * @author yanchaochao
 * @date 2022/3/17 21:55
 */
public class Book {
    private Listlist;
    public void setList(List list) {
        this.list = list;
    }
    public void test(){
        System.out.println(list);
    }
}


bean2.xml





        
        
            JAVA
            C
            MySQL
            C++
            Git
        

        
        
            
        

测试:

package com.spring.testdemo;

import com.spring.collectiontype.Book;
import com.spring.collectiontype.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author yanchaochao
 * @date 2022/3/17 22:03
 */
public class TestBook {
    @Test
    public void testBook(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
        Book book = context.getBean("book", Book.class);
        book.test();

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JH1BJ9hR-1649754754228)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220317221208513.png)]


(5)IOC操作Bean管理(FactoryBean)

  1. Spring有两种类型Bean,一种普通bean,另外一种工厂bean(FactoryBean)

  2. 普通Bean:在配置文件中定义Bean类型就是返回类型

  3. 工厂Bean:在配置文件定义Bean类型可以和返回类型不一样

    第一步:创建类,让这个类作为工厂bean,实现接口FactoryBean

    第二步:实现接口里面的方法,在实现的方法中定义返回的bean类型

    MyBean.java

    package com.spring.factorybean;

    import com.spring.collectiontype.Course;
    import org.springframework.beans.factory.FactoryBean;

    /**

    • @author yanchaochao

    • @date 2022/3/17 22:21
      */
      public class MyBean implements FactoryBean {

      //定义类型和返回类型不一样
      //定义返回bean
      @Override
      public Course getObject() throws Exception {
      Course course = new Course();
      course.setCname(“abc”);
      return course;
      }

      @Override
      public Class getObjectType() {
      return null;
      }

      @Override
      public boolean isSingleton() {
      return FactoryBean.super.isSingleton();
      }
      }

    bean3.xml

    
    
    
    

测试:

package com.spring.testdemo;

import com.spring.collectiontype.Course;
import com.spring.collectiontype.Stu;
import com.spring.factorybean.MyBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author yanchaochao
 * @date 2022/3/17 22:23
 */
public class Testfactorybean {
    @Test
    public void testFactoryBean(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
        Course course = context.getBean("myBean", Course.class);
        System.out.println(course);

    }
}

image-20220317223348754

(6)IOC操作Bean管理(Bean的作用域)

1.在Spring里面,设置创建Bean实例时单实例还是多实例

2.在Spring里面,默认情况下,bean是单实例对象

image-20220317223812033

由图可得出,输出的两个地址是一样的,所以可以得出在默认情况下bean是单实例对象

3.如何设置单实例还是多实例

(1)在Spring配置文件bean标签里面有属性用于设置单实例还是多实例

(2)scope属性值

第一个值 默认值,singleton,表示单实例对象

第二个值 prototype,表示多实例对象

image-20220317224833314

测试:

image-20220317224900140

两个对象的地址不一样

(3)singleton和prototype区别

  1. singleton表示单实例,prototype表示多实例

  2. 设置scope值是singleton时候,加载spring的时候就会创建单实例对象

    设置scope值是prototype时候,不是在加载spring配置文件时候创建对象,在调用getBean方法创建多实例对象

(7)IOC操作Bean管理(生命周期)

1.生命周期

从对象到对象销毁的过程

2.bean生命周期

(1)通过构造器创建bean实例(无参数构造)

(2)为bean的属性设置值和对其他bean的引用(调用set方法)

(3)调用bean的初始化的方法(需要进行配置)

(4)bean可以直接使用了(对象获取到了)

(5)当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁)

3.演示bean的生命周期
Order.java


package com.spring.bean;

/**
 * @author yanchaochao
 * @date 2022/3/18 19:48
 */
public class Order {
    private String oname;


    //无参数构造
    public Order(){
        System.out.println("第一步,执行无参构造实例");
    }

    public void setOname(String oname) {
        this.oname = oname;
        System.out.println("第二步,调用set方法调用初始化值");
    }

    //创建执行初始化的方法
    public void initMethod(){
        System.out.println("第三部,执行初始化方法");
    }

    //执行销毁的方法
    public void destroyMethod(){
        System.out.println("第五步执行销毁的方法");
    }
}


bean4.xml






    
        

    


测试:

Testbean.java


package com.spring.testdemo;

import com.spring.bean.Order;
import com.spring.collectiontype.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author yanchaochao
 * @date 2022/3/18 19:54
 */
public class Testbean {
    @Test
    public void testBook(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
        Order order = context.getBean("orders", Order.class);
        System.out.println("第四步,得到对象");
        System.out.println(order);


        //手动销毁
        context.close();
    }
}

image-20220318201241405

4.bean的后置处理

(1)通过构造器创建bean实例(无参数构造)

(2)为bean的属性设置值和对其他bean的引用(调用set方法)

(3)把bean实例传递bean后置处理器的方法

postProcessBeforeInitialization

(4)调用bean的初始化的方法(需要进行配置)

(5)把bean实例传递bean后置处理器的方法

postProcessAfterInitialization

(6)bean可以直接使用了(对象获取到了)

(7)当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁)

5.演示添加后置处理器效果

(1)创建类,实现接口BeanPostProcessor,创建后置处理器

MyBeanPost.java


package com.spring.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.Nullable;

/**
 * @author yanchaochao
 * @date 2022/3/18 20:17
 */
public class MyBeanPost implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之前执行的方法");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("在初始化之后执行的方法");
        return bean;
    }
}


Order.java


package com.spring.bean;

/**
 * @author yanchaochao
 * @date 2022/3/18 19:48
 */
public class Order {
    private String oname;


    //无参数构造
    public Order(){
        System.out.println("第一步,执行无参构造实例");
    }

    public void setOname(String oname) {
        this.oname = oname;
        System.out.println("第二步,调用set方法调用初始化值");
    }

    //创建执行初始化的方法
    public void initMethod(){
        System.out.println("第三部,执行初始化方法");
    }

    //执行销毁的方法
    public void destroyMethod(){
        System.out.println("第五步执行销毁的方法");
    }
}


bean4.xml






    
        

    
    
    



Testbean.java


package com.spring.testdemo;

import com.spring.bean.Order;
import com.spring.collectiontype.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author yanchaochao
 * @date 2022/3/18 19:54
 */
public class Testbean {
    @Test
    public void testBook(){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
        Order order = context.getBean("orders", Order.class);
        System.out.println("第四步,得到对象");
        System.out.println(order);

        //手动销毁
        context.close();
    }
}

image-20220318203035929

(8)IOC操作Bean管理(xml自动装配)

1.什么是自动装配

(1)根据指定装配规则(属性名称或者属性类型),spring自动将匹配的属性值进行注入

2.演示自动装配

(1)根据属性名称自动注入

 
    

根据属性名称注入,注入值bean的id值和类属性名称一样

(2)根据属性类型自动注入

   
    

(9)IOC操作Bean管理(外部属性文件)

1.直接配置数据库信息

(1)配置德鲁伊连接池

 
    
        
        
        
        
    
2.引入外部属性文件配置数据库连接池

(1)创建外部属性文件,properties格式文件,写数据库信息

image-20220318213847931

(2)把外部properties属性文件引入到配置文件

*引入context名称空间



(3)在spring配置文件中使用标签引入外部属性文件





    
        
        
        
        
    

4.IOC操作Bean管理(基于注解)

1.什么是注解

(1)注解是代码特殊标记,格式:@注解名称**(属性名称=属性值,属性名称=属性值)**

(2)使用注解,注解作用在类上面,方法上面,属性上面

(3)使用注解目的:简化xml配置

2.Spring针对Bean管理中创建对象提供注解

(1)@Component

(2)@Service

(3)@Controller

(4)@Repository

*上面四个注解功能是一样的,都可以用来创建bean实例

3.基于注解方式实现对象创建

(1)引入依赖

image-20220318220453709

(2)开启组件扫描

(3)创建类,在类上面添加创建对象注解

package com.atguigu.spring5.testdemo;
import com.atguigu.spring5.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author yanchaochao
 * @date 2022/3/22 14:31
 */
public class TestSpring5Demo1 {


    @Test
    public void testService(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }
}

image-20220322160123500

实例一:

image-20220322164728767

实例二:

image-20220322164826813

4.基于注解方式实现属性注入

(1)@AutoWired:根据属性类型自动装配

第一步:把service和dao对象创建,在service和dao类添加创建对象注解

第二步:在service注入dao对象,在service类添加dao类型属性,在属性上面使用注解

@Service
public class UserService {
    //定义dao类型的属性
    //不需要添加set方法
    //添加注入属性注解
    @Autowired
    private UserDao userDao;
    public void add(){
        System.out.println("service add.....");
        userDao.add();
    }
}


UserDao.java


package com.atguigu.spring5.dao;
public interface UserDao {
    public void add();
}


UserDaoImpl


import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao{
    @Override
    public void add(){
        System.out.println("dao add...");
    }
}


UserService.java


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@Service
public class UserService {
    //定义dao类型的属性
    //不需要添加set方法
    //添加注入属性注解
    @Autowired
    private UserDao userDao;

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

测试:

TestSpring5Demo1.java


package com.atguigu.spring5.testdemo;

import com.atguigu.spring5.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring5Demo1 {
    @Test
    public void testService(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }
}

image-20220322173557680

(2)@Qualifier:根据属性名称进行注入

这个@Qualifier注解的使用,和上面@Autowired一起使用

(3)@Resource:可以根据类型注入,可以根据名称注入

(4)@Value:注入普通类型属性

5.完全注解开发

(1)创建配置类,替代xml的配置文件

package com.atguigu.spring5.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration  //作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"com.atguigu"})
public class SpringConfig {
}

(2)编写测试类

 @Test
    public void testService2(){
        //加载配置类
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }


三.AOP

1.简介

AOP(面向切面编程)

AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

主要功能

日志记录,性能统计,安全控制,事务处理,异常处理等等。

主要意图

将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

eg:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CZDxwnkh-1649754754232)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220322201401950.png)]

2.底层原理

一,AOP底层使用动态代理

(1)有两种情况

第一种:有接口的情况,使用JDK代理

创建接口实现代理对象,增强类的方法

image-20220322201819596

第二种:没有接口的情况,使用CGLIB代理

创建子类的代理对象,增强类的方法

image-20220322202018929

3.AOP(JDK动态代理)

一,使用JDK动态代理,使用Proxy类里面的方法创建代理对象

image-20220322202338715

调用newProxyInstance方法

image-20220322202417803

方法里有三个参数:

one:类加载器

two:增强方法所在的类,这个类实现的接口,支持多个接口

three:实现这个接口InvocationHandler,创建代理对象,写增强的方法

二,JDK动态代理代码

(1)创建接口,定义方法

package com.study;

public interface UserDao {

    public int add(int a,int b);

    public String update(String id);

}

(2)创建接口实现类,实现方法

package com.study;

public class UserDaoImpl implements UserDao{

    @Override
    public int add(int a, int b) {
        System.out.println("add方法执行了......");
        return a+b;
    }

    @Override
    public String update(String id) {
        System.out.println("update方法执行了......");
        return id;
    }
}

(3)使用Proxy类创建接口代理对象

package com.study;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

/**
 * @author yanchaochao
 * @date 2022/3/22 20:39
 */
public class JDKProxy {
    public static void main(String[] args) {
        //创建接口实现类代理对象
        Class [] interfaces = {UserDao.class};

        UserDaoImpl userDao = new UserDaoImpl();
        UserDao dao =(UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));

        int result = dao.add(1,2);
        System.out.println("result:"+result);
    }
}
//创建代理对象代码
class UserDaoProxy implements InvocationHandler{

    //1.把创建的是谁的代理对象,把谁传递过来
    //有参数构造传递
    private Object object;
    public UserDaoProxy(Object object){
        this.object = object;
    }


    //增强的逻辑
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //方法之前
        System.out.println("方法之前执行......"+method.getName()+":传递参数..."+ Arrays.toString(args));

        //被增强的方法
        Object res = method.invoke(object, args);

        //方法之后
        System.out.println("方法执行之后......"+object);
        return res;
    }
}

结果:

image-20220322215312057

4.AOP(术语)

一,连接点

二,切入点

三,通知(增强)

四,切面

image-20220322220325201

5.AOP操作(准备)

1.Spring框架一般基于AspectJ实现AOP操作

(1)什么是AspectJ

*AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作

2.基于AspectJ实现AOP操作

(1)基于xml配置文件实现

(2)jiyu注解方式实现

3.在项目工程里面引入AOP相关依赖

image-20220323171157660

4.切入点表达式

(1)切入点表达式作用:知道对哪个类型里面的哪个方法进行增强


(2)语法结构:

execution([][][][][][][][][权限修饰符] [返回类型] [类全路径] [方法名称] [参数列表])

举例1:对com.atguigu.dao.BookDao类里面的add进行增强

execution(*com.atguigu.dao.BookDao.add(…方法中的参数))

举例2:对com.atguigu.dao.BookDao类里面的所有方法进行增强

execution(*com.atguigu.dao.BookDao. * (…方法中的参数))

举例3:对com.atguigu.dao包里面的所有类,类里面的所有方法进行增强

execution(*com.atguigu.dao. *. * (…方法中的参数))


6.AOP操作(AspectJ注解)

1.创建类,在类里面定义方法
2.创建增强类(编写增强逻辑)

(1)在增强类里面,创建方法,让不同方法代表不同通知类型

package com.study.aopanno;
import org.springframework.stereotype.Component;
//被增强的类
@Component
public class User {
    public void add (){
        System.out.println("add...");
    }
}


package com.study.aopanno;

import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

//增强的类
@Component
@Aspect  //生成代理对象
public class UserProxy {

    //前置通知
    public void before(){
        System.out.println("before......");
    }
}
3.进行通知的配置

(1)在spring配置文件中,开启注解扫描

bean1.xml




    
    
    

(2)使用注解创建User和UserProxy对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1btLVhd8-1649754754235)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220323175417167.png)]

image-20220323175443242

(3)在增强类上面添加注解@Aspect

image-20220323175619627

(4)在spring配置文件中开启代理生成对象



4.配置不用类型的通知

(1)在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置

package com.study.aopanno;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @author yanchaochao
 * @date 2022/3/23 17:34
 */

//增强的类
@Component
@Aspect  //生成代理对象

public class UserProxy {



    //前置通知
    //Before注解表示为前置通知
    @Before(value = "execution(* com.study.aopanno.User.add(..))")

    public void before(){
        System.out.println("before......");
    }
    //最终通知
    @After(value = "execution(* com.study.aopanno.User.add(..))")
    public void after(){
        System.out.println("after......");
    }

    //后置通知(返回通知)
    @AfterReturning(value = "execution(* com.study.aopanno.User.add(..))")
    public void afterReturning(){
        System.out.println("afterReturning......");
    }
    //异常通知
    @AfterThrowing(value = "execution(* com.study.aopanno.User.add(..))")
    public void afterThrowing(){
        System.out.println("afterThrowing......");
    }

    //环绕通知
    @Around(value = "execution(* com.study.aopanno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
        System.out.println("环绕之前......");


        //被增强的方法
        proceedingJoinPoint.proceed();

        System.out.println("环绕之后......");
    }
}

TestAop.java

package com.study.test;

import com.study.aopanno.User;
import jdk.jfr.StackTrace;
import org.springframework.context.ApplicationContext;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAop {



    @Test
    public void testAopAnno(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        User user = context.getBean("user", User.class);
        user.add();

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xnZT7SSR-1649754754236)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220323225111843.png)]

5.公共切入点抽取
package com.study.aopanno;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

//增强的类
@Component
@Aspect  //生成代理对象

public class UserProxy {




    //相同切入点抽取
    @Pointcut(value = "execution(* com.study.aopanno.User.add(..))")
    public void piontdemo(){

    }


    //前置通知
    //Before注解表示为前置通知
    @Before(value = "piontdemo()")

    public void before(){
        System.out.println("before......");
    }
    //最终通知
    @After(value = "execution(* com.study.aopanno.User.add(..))")
    public void after(){
        System.out.println("after......");
    }

    //后置通知(返回通知)
    @AfterReturning(value = "execution(* com.study.aopanno.User.add(..))")
    public void afterReturning(){
        System.out.println("afterReturning......");
    }
    //异常通知
    @AfterThrowing(value = "execution(* com.study.aopanno.User.add(..))")
    public void afterThrowing(){
        System.out.println("afterThrowing......");
    }

    //环绕通知
    @Around(value = "execution(* com.study.aopanno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
        System.out.println("环绕之前......");
        //被增强的方法
        proceedingJoinPoint.proceed();

        System.out.println("环绕之后......");
    }
}

image-20220323225505972

6.有多个增强类多同一个方法进行增强,设置增强类优先级

(1)在增强类上面添加注解@Order(数字类类值),数字类值越小优先级越高

PersonPerxy.java


package com.study.aopanno;


import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Order(1)
public class PersonPerxy {
     //后置通知(返回通知)
        @Before(value = "execution(* com.study.aopanno.User.add(..))")
        public void afterReturning(){
            System.out.println("Person Before......");
        }
}


User.java


package com.study.aopanno;
import org.springframework.stereotype.Component;

//被增强的类
@Component
public class User {
    public void add (){
        System.out.println("add...");
    }
}


UserProxy.java


package com.study.aopanno;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;


//增强的类
@Component
@Aspect  //生成代理对象
@Order(3)
public class UserProxy {




    //相同切入点抽取
    @Pointcut(value = "execution(* com.study.aopanno.User.add(..))")
    public void piontdemo(){

    }


    //前置通知
    //Before注解表示为前置通知
    @Before(value = "piontdemo()")

    public void before(){
        System.out.println("before......");
    }
    //最终通知
    @After(value = "execution(* com.study.aopanno.User.add(..))")
    public void after(){
        System.out.println("after......");
    }

    //后置通知(返回通知)
    @AfterReturning(value = "execution(* com.study.aopanno.User.add(..))")
    public void afterReturning(){
        System.out.println("afterReturning......");
    }
    //异常通知
    @AfterThrowing(value = "execution(* com.study.aopanno.User.add(..))")
    public void afterThrowing(){
        System.out.println("afterThrowing......");
    }

    //环绕通知
    @Around(value = "execution(* com.study.aopanno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{
        System.out.println("环绕之前......");


        //被增强的方法
        proceedingJoinPoint.proceed();

        System.out.println("环绕之后......");
    }
}

测试:

package com.study.test;

import com.study.aopanno.User;
import jdk.jfr.StackTrace;
import org.springframework.context.ApplicationContext;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAop {
    @Test
    public void testAopAnno(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        User user = context.getBean("user", User.class);
        user.add();

    }
}

image-20220324163819711

7.AOP操作(AspectJ配置文件)

(1)创建两个类,增强类和被增强类,创建方法

package com.study.aopxml;


public class Book {
    public void buy(){
        System.out.println("buy.......");
    }
}


package com.study.aopxml;

public class BookProxy {
    public void Before(){
        System.out.println("before.......");
    }
}

(2)在spring配置文件中创建两个类对象

(3)在spring配置文件中配置切入点




    
    




    
        
        
        
        
            
            
        


    

测试:

@Test
    public void testBook(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
        Book book = context.getBean("book", Book.class);
        book.buy();

    }

image-20220324170748217


完全使用注解开发

不需要创建xml文件

package com.study.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;


@Configuration

@ComponentScan(basePackages = {"com.study"})

@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
    
}


四.JdbcTemplate

1.概念和准备

1.什么是JdbcTemplate

Spring框架对JDBC进行封装,使用JdbcTemplate方便对实现数据库操作

2.准备工作

(1)引入相关的jar包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iHCSmQ2K-1649754754237)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220328152239741.png)]

image-20220328152320647

(2)在Spring配置文件中配置数据库的连接池


    
        
        
        
        
    

(3)JdbcTemplate对象,注入DataSource


    
        
        
    

(4)创建service类,创建dao类,在dao注入jdbcTemplate对象

配置文件中开启组件扫描


    

service

@Service
public class BookService {
    //注入dao
    @Autowired
   private BookDao bookDao;
}

dao

@Repository
public interface BookDao {

}


public class BookDaoImpl implements BookDao{

    //注入JdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;
}

2.JdbcTemplate操作数据库

(1)添加

1.对应数据库创建实体类

image-20220410104650909

2.编写service和dao

(1)在dao进行数据库添加操作

(2)调用jdbcTemplate对象里面的update方法实现

image-20220410105159471

*有两个参数

*第一个参数:sql语句

*第二个参数:可变参数,设置sql语句值

public class BookDaoImpl implements BookDao{


    //注入JdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void add(Book book) {
        //1.创建sql语句
        String sql = "insert into t_book values(?,?,?)";

        //2.调用方法实现
        Object [] args = {book.getUserId(),book.getUsername(),book.getUstatus()};
        int update = jdbcTemplate.update(sql,args);
        //用法不一
//      int update = jdbcTemplate.update(sql,book.getUserId(),book.getUsername(),book.getUstatus());
        System.out.println(update);
    }
}

测试类Test:

package com.study.test;

import com.study.entity.Book;
import com.study.service.BookService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author yanchaochao
 * @date 2022/4/10 10:58
 */
public class TestBook {
    @Test
    public void testJdbcTemplate(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService", BookService.class);

        Book book = new Book();
        book.setUserId("1");
        book.setUsername("java");
        book.setUstatus("a");

        bookService.addBook(book);
    }
}

image-20220410112111306

image-20220410112449907


(2)修改删除

//修改
    @Override
    public void update(Book book) {
        //1.创建sql语句
        String sql = "update t_book set username=?,ustatus=?where user_id=?";

        //2.调用方法实现
        Object [] args = {book.getUsername(),book.getUstatus(),book.getUserId()};
        int update = jdbcTemplate.update(sql,args);
        System.out.println(update);
    }

    //删除
    @Override
    public void delete(String id) {
        //1.创建sql语句
        String sql = "delete from t_book where  user_id=?";
        //2.调用方法实现
        int update = jdbcTemplate.update(sql,id);
        System.out.println(update);
    }

测试Test

源数据库

image-20220410115527148

修改:

@Test
    public void testup(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService", BookService.class);

        //修改
        Book book = new Book();
        book.setUserId("1");
        book.setUsername("javaupup");
        book.setUstatus("study");
        bookService.updateBook(book);

    }

image-20220410115616868

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0gZs5wJK-1649754754239)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220410115626964.png)]

删除:

 @Test
    //删除
    public void testdelete(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService", BookService.class);

        bookService.deleteBook("2");

    }

image-20220410115707189

image-20220410115719863

(3)查询

1.查询返回某个值

1.查询表里有多少条记录,返回某个值

image-20220410120637509

2.使用JdbcTemplate实现查询返回某个值代码

//查询表记录数
    @Override
    public int selectCount() {
        //1.创建sql语句
        String sql = "select count(*) from t_book";
        //2.调用方法实现
        Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
        return count;
    }


@Test
    //查询表返回某个值
    public void testselect(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService", BookService.class);

        int count = bookService.findCount();
        System.out.println(count);
    }

此时数据库中有3条数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nGmkYwnr-1649754754240)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220410121305524.png)]

执行程序后返回:3

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ml1erd7Q-1649754754241)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220410121314652.png)]


2.查询返回对象

(1)场景:查询图书详细

(2)JdbcTemplate实现查询返回对象

image-20220410134427727

有三个参数:

第一个参数:sql语句

第二个参数:RowMapper,是接口,返回不同类型数据,使用接口里面实现类完成数据封装

第三个参数:sql语句值

//查询返回对象
    public Book findCountdx(String id){
        return bookDao.findBookInfo(id);
    }


//查询返回对象
    @Override
    public Book findBookInfo(String id) {
        //1.创建sql语句
        String sql = "select * from t_book where user_id=?";
        //2.调用方法实现
        Book book = jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper(Book.class),id);
        return book;
    }


@Test
    //查询返回对象
    public void testselectdx(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService", BookService.class);

        Book book = bookService.findCountdx("1");
        System.out.println(book);
    }

image-20220410135641428

image-20220410135656682


3.查询返回集合

(1)场景:查询图书列表分页

(2)调用JdbcTemplate方法实现查询返回集合

image-20220410140153482

有三个参数:

第一个参数:sql语句

第二个参数:RowMapper,是接口,返回不同类型数据,使用接口里面实现类完成数据封装

第三个参数:sql语句值

//查询返回集合
    public List findCountjh(){
        return bookDao.findAllBook();
    }


@Override
    public List findAllBook() {
        //1.创建sql语句
        String sql = "select * from t_book ";
        //2.调用方法实现
        List books = jdbcTemplate.query(sql,new BeanPropertyRowMapper(Book.class));
        return books;
    }


@Test
    //查询返回集合
    public void testselectjh(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService", BookService.class);

        List all = bookService.findCountjh();
        System.out.println(all);
    }

image-20220410140849548

image-20220410140803868


(4)批量添加

1.批量操作:操作表里面多条记录

2.JdbcTemplate实现批量添加操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oLqmc1OT-1649754754243)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220410141040597.png)]

有两个参数

第一个参数:sql语句

第二个参数:List集合,添加多条记录数据

//批量添加
    public void batchAdd(ListbatchArgs){
        bookDao.batchAddBook(batchArgs);
    }


    //批量添加
    @Override
    public void batchAddBook(List batchArgs) {
        //1.创建sql语句
        String sql = "insert into t_book values(?,?,?)";
        //2.调用方法实现
        int [] ints = jdbcTemplate.batchUpdate(sql,batchArgs);
        System.out.println(Arrays.toString(ints));
    }


@Test
    //批量添加
    public void testbatchAdd(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService", BookService.class);

        ListbatchArgs = new ArrayList<>();
        Object[] o1 = {"3","java","a"};
        Object[] o2 = {"4","c++","b"};
        Object[] o3 = {"5","MySQL","c"};
        batchArgs.add(o1);
        batchArgs.add(o2);
        batchArgs.add(o3);
        bookService.batchAdd(batchArgs);

    }

image-20220410143416367

image-20220410143403581

image-20220410143428501


(5)批量修改

//批量修改
    public void batchUpdate(ListbatchArgs){
        bookDao.batchUpdate(batchArgs);
    }


 //批量修改
    @Override
    public void batchUpdate(List batchArgs) {
        //1.创建sql语句
        String sql = "update t_book set username=?,ustatus=?where user_id=?";
        //2.调用方法实现
        int [] ints = jdbcTemplate.batchUpdate(sql,batchArgs);
        System.out.println(Arrays.toString(ints));
    }


@Test
    //批量修改
    public void testbatchUpdate(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService", BookService.class);

        ListbatchArgs = new ArrayList<>();
        Object[] o1 = {"java0909","a3","3"};
        Object[] o2 = {"c++1010","b4","4"};
        Object[] o3 = {"MySQL1111","c5","5"};
        batchArgs.add(o1);
        batchArgs.add(o2);
        batchArgs.add(o3);
        bookService.batchUpdate(batchArgs);

    }

image-20220410143938993

image-20220410144357899

image-20220410144425107

(6)批量删除

//批量删除
    public void batchDelete(ListbatchArgs){
        bookDao.batchDelete(batchArgs);
    }


//批量删除
    @Override
    public void batchDelete(List batchArgs) {
        //1.创建sql语句
        String sql = "delete from t_book where  user_id=?";
        //2.调用方法实现
        int [] ints = jdbcTemplate.batchUpdate(sql,batchArgs);
        System.out.println(Arrays.toString(ints));
    }


@Test
    //批量删除
    public void testbatchDelete(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        BookService bookService = context.getBean("bookService", BookService.class);

        ListbatchArgs = new ArrayList<>();
        Object[] o1 = {"3"};
        Object[] o2 = {"4"};
        Object[] o3 = {"5"};
        batchArgs.add(o1);
        batchArgs.add(o2);
        batchArgs.add(o3);
        bookService.batchDelete(batchArgs);

    }

image-20220410144926945

image-20220410144954069

image-20220410145006387



五.事物

1.什么是事物

(1)事物是数据库操作最基本单元

(2)典型场景:银行转账

*lucy转账100元给mary

*lucy少100,mary多100

2.事物四个特性(ACID)

(1)原子性

(2)一致性

(3)隔离性

(4)持久性

3.搭建事物操作环境

image-20220410150741560

1.创建数据库表,添加记录

image-20220410151241877

2.创建service,搭建dao,完成对象创建和注入关系

service注入dao,在dao注入JdbcTemplate注入DataSource

service

@Service
public class UserService {
    //注入dao
    @Autowired
    private UserDao userDao;
}

dao

public interface UserDao {

}


@Repository
public class UserDaoImpl implements UserDao{


    @Autowired
    private JdbcTemplate jdbcTemplate;

}

3.在dao中创建两个方法,多钱方法和少钱的方法,在service创建(转账的方法)

代码如下

bean2.xml



    
    




    
    

    
    
        
        
        
        
    

    
    
        
        
    



UserService.java


package com.shiwu.service;

import com.shiwu.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author bcy
 * @date 2022/4/10 15:17
 */
@Service
public class UserService {
    //注入dao
    @Autowired
    private UserDao userDao;

    //转账的方法
    public void accountMoney(){

        //lucy少100
        userDao.reduceMoney();

        //mary多100
        userDao.addMoney();
    }
}


UserDao.java


package com.shiwu.dao;

/**
 * @author yanchaochao
 * @date 2022/4/10 15:18
 */
public interface UserDao {

    //多钱
    public void addMoney();
    //少钱
    public void reduceMoney();

}


UserDaoImpl.java


package com.shiwu.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

/**
 * @author yanchaochao
 * @date 2022/4/10 15:18
 */
@Repository
public class UserDaoImpl implements UserDao{

    @Autowired
    private JdbcTemplate jdbcTemplate;


    //少钱
    @Override
    public void reduceMoney() {
        String sql = "update t_account set money = money - ?  where username = ?";
        jdbcTemplate.update(sql,100,"lucy");

    }
    //多钱
    @Override
    public void addMoney() {
        String sql = "update t_account set money = money + ?  where username = ?";
        jdbcTemplate.update(sql,100,"mary");
    }

}

测试:

test.java

package com.shiwu.test;

import com.shiwu.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class test {
    @Test
    public void testAccount(){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
        UserService userService = context.getBean("userService", UserService.class);
        userService.accountMoney();
    }
}

image-20220410153740607

image-20220410153711681

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KNkl0w8m-1649754754248)(C:UserslenovoAppDataRoamingTypora ypora-user-imagesimage-20220410153800792.png)]

4.模拟转账过程中异常

在lucy给mary转账的过程lucy可能会出现断网问题,lucy钱少了但是mary钱可能没有多。

image-20220411143031130

image-20220411143046788

出现异常:

image-20220411143115893

image-20220411143124464

(1)上面问题如何解决?

*使用事物进行解决

(2)事物操作过程

image-20220411143419514

5.事务操作(介绍)

(1)事物一般添加到JavaEE三层结构里面Service层(业务逻辑层)

(2)在Spring进行事务管理操作

有两种方式:编程式事务管理和声明式事务管理(使用)

(3)声明式事务管理

1.基于注解方式(使用

2.基于xml配置文件方式

(4)在Spring进行声明式事务管理,底层使用AOP原理

(5)Spring事务管理API

1.提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类

image-20220411145546266

6.事务操作(注解声明式事物管理)

1.在spring配置文件中配置事务管理器


    
        
        
    

2.在spring中配置文件,开启事务注解

(1)在spring配置文件中引入名称空间tx


(2)开启事务注解



(3)在Service类上面(获取service类里面方法上面)添加事务注解

*@Transactional可以添加到类上面,也可以添加到方法上面

*如果把这个注解添加到类上面,这个类里面的所有方法都添加事务

*如果把这个注解添加到方法上面,为这个方法添加事务

@Service
@Transactional
public class UserService {

image-20220411151222090

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eyanAUTm-1649754754250)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220411151231304.png)]

数据库数据未改变

7.事务操作(声明式事物管理参数配置)

(1)配置

在service类上面添加注解@Transactional,在这个注解里面可以配置事务相关参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3tLZMK1z-1649754754250)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220411151737560.png)]

(2)propagation:事务传播行为

多事务方法直接进行调用,这个过程中事务时如何进行管理的

image-20220411153226620

image-20220411152932336

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xkda58zO-1649754754251)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220411153353803.png)]

(3)ioslation:事务隔离级别

  1. 事务有特性成为隔离性,多事务操作之间不会产生影响。不考虑隔离性产生很多问题
  2. 有三个读问题:脏读,不可重复读,虚(幻)读
  3. 脏读:一个未提交事务读取到另一个未提交事务的数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O07HR01A-1649754754251)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220411153724419.png)]

  1. 不可重复读:一个未提交事务读取到另一个提交事务修改数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZNzybYkP-1649754754252)(https://gitee.com/yan-chaochao/typora-library/raw/master/typora-library/image-20220411154552547.png)]

  1. 虚(幻)读:一个未提交事务读取另一个提交事务添加数据
  2. 解决:通过设置事务隔离级别,解决读问题

image-20220411154907495

(可重复读为默认隔离级别)

image-20220411155039690

(4)timeout:超时时间

1.事务需要在一定时间内进行提交,如果不提交进行回滚

2.默认值是 -1,设置时间以秒单位进行计算

(5)readOnly:是否只读

1.读:查询操作,写:添加修改删除操作

2.readOnly默认值false,表示可以查询,可以添加修改删除操作

3.设置readOnly值是true,设置成true之后,只能查询

(6)rollbackFor:回滚

设置出现哪些异常不进行回滚

(7)noRollbackFor:不回滚

设置出现哪些异常不进行事务回滚

8.事务操作(xml声明式事务管理)

(1)在Spring配置文件中配置

第一步 配置事务管理器

第二步 配置通知

第三步 配置切入点和切面

9.事务操作(完全注解声明式事务管理)

1.创建配置类,使用配置类代替xml配置文件

你可能感兴趣的:(面试,学习路线,阿里巴巴,android,前端,后端)