spring基础知识和用法

文章目录

总结

1.1 web项目开发中的耦合度问题

  • 在Servlet中需要调用service中的方法,则需要在Servlet类中通过new关键字创建Service的实例
public interface ProductService{
        public List<Product> listProducts();
    }
public class ProductServiceImpl1 implements ProductService{
        public List<Product> listProducts(){
            //查询热销商品
        }
    }
public class ProductServiceImpl2 implements ProductService{
        public List<Product> listProducts(){
            //查询好评商品
        }
    }
public class ProductListServlet extends HttpServlet{
    //在servlet中使用new关键字创建ProductServiceImpl1对象,增加了servlet和service的耦合度
    private ProductService productService = new ProductServiceImpl1();
    
    protected void doGet(HttpServletRequest request,HttpServletResponse response){
        doPost(request,response);
    }
    protected void doPost(HttpServletRequest request,HttpServletResponse response){
        productService.listProducts();
    }
}

在service实现类中需要调用DAO中的方法,也需要在service实现类通过new关键字创建DAO实现类对象

如果在实现new关键字创建对象:

失去了面向接口编程的灵活性代码的侵入性增强(在一个类中new另外一个,增加了耦合度)、降低了代码的灵活性

类似给jdbc配置一个properties文件一样, 这样就不用在源代码修改

1.2 面向接口编程

面向接口编程
https://note.youdao.com/yws/public/resource/f0a01c0265c577e77f3856baa78d2dce/xmlnote/148E5E23C345489E8495EF1D1828AAB0/13886

解决方案:在Servlet中定义Service接口的对象,不适用new关键字创建实现类对象,在servlet的实例化的时候,通过反射动态的给Service接口的对象变量赋值。

如何实现:Spring可以做到!

1.3 Spring介绍

Spring是一个轻量级的控制反转和面向切面的容器框架,用来解决企业项目开发的复杂度问题——解耦

  • 轻量级:体积小,对代码没有侵入性

  • 控制反转:IoC(Inverse of Control),把创建对象的工作由Spring完成,Spring在创建对象的时候同时可以完成

对象属性赋值(DI)

  • 面向切面:AOP(Aspect Oriented Programming)面向切面编程,可以在不改变原有业务逻辑的情况下实现对业务的增强

  • 容器:实例的容器,管理创建的对象

1.4 Spring架构

  • 官网 https://spring.io/

https://note.youdao.com/yws/public/resource/f0a01c0265c577e77f3856baa78d2dce/xmlnote/8568BDCAD94F47C2BC97DF7372233FE0/13996

  • Spring架构图

https://note.youdao.com/yws/public/resource/f0a01c0265c577e77f3856baa78d2dce/xmlnote/FC1880AD80D84AF3B10B275CC6D54F45/14002

1.4.1 Core Container

Spring容器组件,用于完成实例的创建和管理

  • core 核心

  • beans 实例管理

  • context 容器上下文

1.4.2 AOP、Aspects

Spring AOP组件,实现面向切面编程

  • AOP

  • Aspects

1.4.3 web

Spring web组件实际指的是SpringMVC框架、实现web项目的MVC控制

  • web(Spring对web项目的支持)

  • webmvc(SpringMVC)

1.4.4 Data Access

Spring数据访问组件,也是一个基于JDBC封装的持久层框架(即使没有mybatis,Spring也可以完成持久化的数据库操作)

  • tx

1.4.5 Test

Spring的单元测试组件,提供了Spring环境下的单元测试支持

  • test

二:Spring IoC

Spring Ioc 容器组件,可以完成对象的创建,对象属性赋值,对象管理

2.1 Spring框架部署(IoC)

2.1.1 创建Maven工程

  • Java

  • Web

2.1.2 添加SpringIoc依赖

  • core

  • beans

  • aop

  • expression

  • context

导入这一个context其他包会依赖导入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NH8Lvma2-1651847267951)(E:\typora图片文件\image-20220422123632946.png)]

 
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.12.RELEASE</version>
</dependency>
 

2.1.3 创建Spring配置文件

通过配置文件“告诉”Spring容器创建什么对象,给对象属性赋什么值

  • 在resource目录下创建名为 applicationContext.xml 的文件(文件名可以自定义的)
<?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:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
                            
<!-- xsd规范作用在主标签上-->       
<!-- xsd 可以根据配置引入多个,只要引入了相应的xsd,可以使用相应标签规则属性 如下列的aop规范-->    
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--对于一个xml文件如果作为框架的配置文件,需要遵守框架的配置规则-->
<!--通常一个框架为了开发者能够正确的配置,都会提供xml的规范文件(dtd\xsd)-->

 
 
</beans>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
<!--  规范写在主标签之上的 dtd规划-->
        "http://mybatis.org/dtd/mybatis-3-config.dtd" >
<configuration>

</configuration>

—45集

2.2 SpringIoC使用

使用SpringIoC组件创建并管理对象

2.2.1 创建一个实体类

public class Student {
 
    private String stuNum;
    private String stuName;
    private String stuGender;
    private int stuAge;
    private Date enterenceTime;//入学日期
 
}

2.2.2 在Spring配置文件中配置实体类

<!--通过bean标签将实体类配置给Spring进行管理,id表示实体类的唯一标识(自己定义,一般是类名小写)-->
    <bean id="stu" class="com.liguoqing.ioc.bean.Student">
        <property name="stuNum" value="10002"/>
        <property name="stuName" value="李四"/>
        <property name="stuGender" value=""/>
        <property name="stuAge" value="18"/>
        <property name="enterenceTime" ref="date"/>
    </bean>

2.2.3初始spring对象工厂,获取对象

ClassPathXmlApplicationContext

//通过Spring容器创建Student对象
//1、初始化Spring容器,加载解析这个Spring配置文件 ("applicationContext.xml") 将文件中的内容读取出来放在一个java对象中
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//2、通过Spring容器,获取Student对象
Student student2 = (Student) context.getBean("stu");

2.3 IoC和DI

  • IoC(Inverse of Control) 控制反转,依赖Spring对象工厂,完成对象的创建

  • DI (Dependency Injection)依赖注入,在Spring完成对象创建的同时依赖Spring容器完成对象属性的赋值

2.3.1 IoC

当我们需要通过Spring对象工厂创建某个类的对象时候,需要将这个交给Spring管理——通过bean标签配置

<bean id="book" class="com.liguoqing.ioc.bean.Book"></bean>  

2.3.2 DI

通过Spring容器给创建的对象属性赋值

<!--通过bean标签将实体类配置给Spring进行管理,id表示实体类的唯一标识(自己定义,一般是类名小写)-->
    <bean id="stu" class="com.liguoqing.ioc.bean.Student">
        <property name="stuNum" value="10002"/>
        <property name="stuName" value="李四"/>
        <property name="stuGender" value=""/>
        <property name="stuAge" value="18"/>
        <property name="enterenceTime" ref="date"/>
    </bean>

2.4 DI依赖注入

2.4.1 依赖注入三种方式

Spring容器加载配置文件之后,通过反射创建类的对象,并给属性赋值;

Spring容器通过反射实现属性注入有三种种方式:

  • set方法注入

  • 构造器注入

  • 接口注入(不常用)

2.4.2 set方法注入

image-20220422133313827

在bean标签中通过配置property标签给对象属性赋值,实际上就是通过反射调用set方法完成属性的注入

简单类型以及字符串
  • 直接通过property标签的value属性赋值
<bean id="stu" class="com.liguoqing.ioc.bean.Student">
    <!--简单类型-->
    <property name="stuNum" value="10001"/>
    <!--字符串类型--> 
    <property name="stuName" value="李四"/>
</bean>
日期对象(属性类型是一个类)
  • 方式1:在property标签中通过ref引用Spring容器中的一个对象
   <bean id = "date" class="java.util.Date"></bean>
   
    <bean id="stu" class="com.liguoqing.ioc.bean.Student">
        <property name="enterenceTime" ref="date"/>
    </bean>
  • 方式2:在property标签中添加子标签bean来指定对象
  <bean id="stu" class="com.liguoqing.ioc.bean.Student">
        <property name="enterenceTime">
            <bean class="java.util.Date"/>
        </property>
    </bean>
自定义类对象属性
  • 方式1:
    <bean id="clazz" class="com.liguoqing.ioc.bean.Clazz">
        <property name="classId" value="2010"/>
        <property name="className" value="java2010"/>
    </bean>
    
    <bean id="stu" class="com.liguoqing.ioc.bean.Student">
        <property name="clazz" ref="clazz"/>
    </bean>
  • 方式2:
   <bean id="stu" class="com.liguoqing.ioc.bean.Student">
        <property name="clazz">
            <bean class="com.liguoqing.ioc.bean.Clazz">
                <property name="classId" value="2010"/>
                <property name="className" value="java2010"/>
            </bean>
        </property>
    </bean>
集合类型
  • List

1: List List中的元素是字符串或者简单类型的封装类

   <bean id="stu" class="com.liguoqing.ioc.bean.Student">
        <property name="hobbies" value="旅游,电影"/>
    </bean>
    --------------------或者下面这种引用方式也可以---------------------------------------
    <bean id="stu" class="com.liguoqing.ioc.bean.Student">
           <property name="hobbies">
            <list>
               <value>旅游</value>
               <value>电影</value>
            </list>
        </property>
    </bean>

2:List List中的元素是对象类型

   <bean id="stu" class="com.liguoqing.ioc.bean.Student">
        <property name="hobbies">
            <list>
                <bean class="com.liguoqing.ioc.bean.Book"/>
                <bean class="com.liguoqing.ioc.bean.Book"/>
                <bean class="com.liguoqing.ioc.bean.Book"/>
            </list>
        </property>
    </bean>
 ------------------或者下面这种引用方式也可以-----------------------------------------------------
    <bean id="book" class="com.liguoqing.ioc.bean.Book"></bean>
    <bean id="stu" class="com.liguoqing.ioc.bean.Student">
          <property name="hobbies">
            <list>
                <ref bean="book"></ref>
                <ref bean="book"></ref>
                <ref bean="book"></ref>
            </list>
        </property>
    </bean>   
  • Set
Set 略,自己看list,只需要原来的list标签换成set标签
  • Map

键值对

    <bean id="stu" class="com.liguoqing.ioc.bean.Student">
        <property name="map">
            <map>
                <entry>
                    <key>
                        <value>k1</value>
                    </key>
                    <value>123</value>
                </entry>
                <entry>
                    <key>
                        <value>k2</value>
                    </key>
                    <value>456</value>
                </entry>
            </map>
        </property>
    </bean>
  • Properties
   <bean id="stu" class="com.liguoqing.ioc.bean.Student">
       <property name="properties">
           <props>
               <prop key="key1">aaa</prop>
               <prop key="key2">aaa</prop>    
           </props>
        </property>
    </bean>

—再看49集

2.4.3 构造器注入

简单类型、字符串、对象

 public class Student {
        private String stuNum;
        private String stuName;
        private String stuGender;
        private int stuAge;
        private Date date;
        private Clazz clazz;
    
       public Student(String stuNum, String stuName, String stuGender, int stuAge, Date date, Clazz clazz) {
        this.stuNum = stuNum;
        this.stuName = stuName;
        this.stuGender = stuGender;
        this.stuAge = stuAge;
        this.date = date;
        this.clazz = clazz;
    }
}
 


<bean id="data" class="java.util.Date"></bean>
<bean id="stu" class="com.liguoqing.ioc.bean.Student">
    <constructor-arg index="0" value="10001"/> <!--字符串类型-->
    <constructor-arg value="张三"/>
    <constructor-arg value=""/>
    <constructor-arg value="21"/>  <!--简单类型-->
    <constructor-arg ref="data"/>   <!--对象类型-->
    <constructor-arg >
        <bean class="com.liguoqing.ioc.bean.Clazz"></bean>
    </constructor-arg>    <!--自定义类对象类型-->
 
</bean>

集合类型属性

 
public class Student {
    private List<String> hobbies;
    private Set<String> sets;
    private Map<String,Object> maps;
    private Properties properties;
    
    public Student(List<String> hobbies, Set<String> sets, Map<String, Object> maps, Properties properties) {
         this.hobbies = hobbies;
        this.sets = sets;
        this.maps = maps;
        this.properties = properties;
    }
}


 

 
<bean id="stu2" class="com.liguoqing.ioc.bean.Student">
    <constructor-arg index="0">
        <list>
            <value>11</value>
            <value>13</value>
            <value>12</value>
        </list>
    </constructor-arg>
    <constructor-arg index="1">
        <set>
            <value>11</value>
            <value>13</value>
            <value>12</value>
        </set>
    </constructor-arg>
    <constructor-arg index="2">
        <map>
            <entry>
                <key><value>1</value></key>
                <value>value</value>
            </entry>
            <entry>
                <key><value>2</value></key>
                <value>value2</value>
            </entry>
        </map>
    </constructor-arg>
    <constructor-arg index="3">
        <props>
            <prop key="k1">value1</prop>
            <prop key="k2">value2</prop>
        </props>
    </constructor-arg>
</bean>

2.5 Bean的作用域

1.单例模式:(默认的是单例模式)在Bean标签中可以通过scope属性指定对象的作用域scope=“singleton” 表示当前bean是单例模式

(默认饿汉模式;Spring容器初始化阶段就会完成此对象的创建;

当在bean标签中设置lazy-init=“true” 变为懒汉模式Spring容器初始化阶段就不会完成此对象的创建)

2.非单例模式:scope=“prototype” 表示当前bean是非单例模式,每次通过Spring容器获取此bean的对象时都会创建一个新的对象,

没有懒汉和饿汉的说法

2.5.1单例和多例

单例:创造的对象相同

<bean id="book" class="com.liguoqing.ioc.bean.Book" scope="singleton" ></bean>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aoeNrD7B-1651847267953)(E:\typora图片文件\image-20220422201542364.png)]

多例(没有懒汉和饿汉的说法)

<bean id="book" class="com.liguoqing.ioc.bean.Book" scope="prototype" lazy-init="true"></bean>

创建的对象不同

2.5.2 饿汉和懒汉

饿汉

<bean id="book" class="com.liguoqing.ioc.bean.Book" scope="singleton" lazy-init="false"></bean>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8eVdBEBK-1651847267954)(E:\typora图片文件\image-20220422201912545.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bjMKoDxu-1651847267955)(E:\typora图片文件\image-20220422202035213.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r4OJrDVz-1651847267957)(E:\typora图片文件\image-20220422202123663.png)]

懒汉

<bean id="book" class="com.liguoqing.ioc.bean.Book" scope="singleton" lazy-init="true"></bean>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A158dEvU-1651847267959)(E:\typora图片文件\image-20220422202425456.png)]

2.6 Bean的生命周期方法

<!--在bean标签中可以通过 init-method 属性指定当前bean的初始化方法,初始化方法在构造器执行之后执行-->
    <!--在bean标签中可以通过 destroy-method 属性指定当前bean的销毁方法,销毁方法在对象销毁之前执行-->
 
  • Bean
package com.liguoqing.ioc.bean;
 
public class Book {
    private int bookId;
    private String bookName;
 
 
        //初始化方法:在创建当前类对象时调用的方法,进行一些资源准备工作
    public void init(){
        System.out.println("__________________init");
        this.bookId = 1;
        this.bookName = "初始值";
    }
    
        //销毁方法:在Spring容器销毁对象时调用此方法,进行一些资源回收性的操作
    public void destory(){
        System.out.println("__________destory");
    }
 
}
  • 在Spring配置文件
    <bean id="book" class="com.liguoqing.ioc.bean.Book" scope="prototype"
          init-method="init" destroy-method="destory"></bean>

2.7 自动装配

<!--自动装配:Spring在实例化当前bean的时候从Spring容器中找到匹配的实例赋值给当前bean的属性-->
<!--  autowire="byName" 根据当前Bean的属性名,在Spring容器中寻找匹配的对象,如果根据Name找到了bean,但是类型不匹配则会抛出异常。 -->
<!--  autowire="byType" 根据当前Bean的属性类型,在spring容器中寻找匹配的对象,如果根据类型找打了多个类型匹配的bean,也会抛出异常-->
<bean id="stu3" class="com.liguoqing.ioc.bean.Student" autowire="byName"></bean>

2.7.1 autowire=“byName”

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h2Gu9X1P-1651847267960)(E:\typora图片文件\image-20220422204040285.png)]

2.7.2 autowire=“byType”

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y5YhIB1U-1651847267962)(E:\typora图片文件\image-20220422204510724.png)]

2.8 SpringIoC 工作原理

https://note.youdao.com/yws/public/resource/f0a01c0265c577e77f3856baa78d2dce/xmlnote/A8B294358A69464A9BF360777A35F6AC/14366

非单例模式,不会放入beanMap容器中,而是直接调用

三、SpringIoC——基于注解

SpringIoC的使用,需要我们通过XML将类声明给Spring容器进行管理,从而通过Spring工厂完成对象的创建及属性值的注入;

Spring除了提供基于XML的配置方式,同时提供了基于注解的配置;直接在实体类中添加注解声明Spring容器管理,以简化开发步骤。

3.1 SpringIoC框架部署

3.1.1 创建Maven项目

3.2.2 添加SpringIoC依赖

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.12.RELEASE</version>
</dependency>
 

3.2.3 创建Spring配置文件

  • 因为Spring容器初始化时,只会加载applicationContext.xml文件,那么我们在实体类中添加的注解就不会被Spring扫描,所以我们需要在applicationContext.xml声明Spring的扫描范围,以达到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"
        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:annotation-config/>
<!--    声明Spring工厂注解的扫描范围-->
    <context:component-scan base-package=""/>
 
 
</beans>

3.2 IoC常用注解

类注解

3.2.1 @Component(“stu”)(类的注解)

  • 类的注解,声明此类被Spring容器进行管理,相当于bean标签的作用

  • @Component(value=“类的别名”) value属性用于制定当前bean的id属性,或者叫别名。value属性也可以省略,如果省略,那么当前类的id默认为当前类名首字母改小写

  • @Service、@Controller、@Repository这三个注解也可以将类声明给Spring管理,他们主要是语义上的区别(都是类的注解)

  • @Controller注解主要声明将控制器类配置给Spring管理,例如Servlet

  • @Service注解主要声明业务处理类配置给Spring管理,Service接口的实现类

  • @Repository注解主要声明持久化类配置给Spring管理,DAO接口

  • @Component除了控制器,Service,DAO之外的类一律使用此注解声明

3.2.2 @Scope(value = “prototype”)

  • 类的注解,用于声明当前类单例模式还是非单例模式,相当于bean标签的scope属性

  • @Scope(“propotype”) 表示当前类为非单例模式(默认单例模式)

3.2.3 @Lazy

  • 类注解,用于声明一个单例模式的bean是否为懒汉模式

  • @Lazy(true) 表示声明为懒汉模式,默认为饿汉模式

方法注解

3.2.4 @PostConstruct

  • **方法注解,**声明一个方法为当前类的初始化方法(在构造器之后执行),相当于bean标签的init-method属性

3.2.5 @PreDestroy

  • 方法注解,声明一个方法为当前类的销毁方法(在对象从容器中释放之前执行),相当于bean标签的destory-method属性

属性注解

3.2.6 @Autowired(同时使属性注解和set方法注解)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hzXNGs0d-1651847267965)(E:\typora图片文件\image-20220422221930736.png)]\

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ws54I0Bs-1651847267966)(E:\typora图片文件\image-20220422222319101.png)]

  • **属性注解、方法注解(set)**声明当前属性自动装配,默认byType,默认必须(如果没有找到类型与属性类型匹配的bean则抛出异常)

  • @Autowired(required = false) 通过required属性设置当前自动装配是否为必须(默认必须(true)——如果没有找到类型与属性类型匹配的bean则抛出异常)

    byType

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ef7ybzUW-1651847267968)(E:\typora图片文件\image-20220422224325026.png)]

  • byName

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FlYPBtUH-1651847267969)(E:\typora图片文件\image-20220423001803028.png)]

    @Qualifier(“a”) 通过id

@Autowired(required = false)
public void setClazz(@Qualifier("a") Clazz clazz) {
    this.clazz = clazz;
}

3.2.7 @Resource

  • 属性注解,也用于声明属性自动装配

  • 默认装配方式为byName,如果根据byName没有找到相应的bean,则继续根据byType寻找对应的bean,根据byType如果没找到bean,或者找到不止一个类型匹配的bean则抛出异常。

四、代理设计模式

4.1 生活中的代理

https://note.youdao.com/yws/public/resource/f0a01c0265c577e77f3856baa78d2dce/xmlnote/01B7459A05D74E79927416B5C349A35B/14536

代理设计模式的优点:将通用性的工作交由代理对象完成,被代理对象只需专注自己的核心业务。

4.2 静态代理

静态代理,代理类只能够为特定的类生产代理对象,不能代理任意类

Test类

https://note.youdao.com/yws/public/resource/f0a01c0265c577e77f3856baa78d2dce/xmlnote/FAB4AD3FE3654A638C5015D51A590F37/14547

使用代理的好处

  1. 被代理类中只用关注核心业务的实现,将通用的管理型逻辑(事务管理、日志管理)和业务逻辑分离
  2. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YuJi94fP-1651847267973)(E:\typora图片文件\image-20220423094449774.png )]
  3. 将通用的代码放在代理类中实现,提高了代码的复用性
  4. [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zAitPTkf-1651847267975)(E:\typora图片文件\image-20220423094543545.png)]
  5. 通过在代理类添加业务逻辑,实现对原有业务逻辑扩展(增强)

4.3 动态代理

动态代理,几乎可以为所有的类产生代理对象

动态代理的实现方式有两种:

JDK动态代理

CGLib动态代理

4.3.1JDK动态代理

接口(GenaralDAO)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sRiWKpS2-1651847267977)(E:\typora图片文件\image-20220423103943532.png)]

两个接口实现类(BookDAOImpl,StudentDAOImpl)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NyD9Z0Jz-1651847267984)(E:\typora图片文件\image-20220423103836902.png)]

代理类JDKMyDynamicProxy

package com.liguoqing.dao;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
/**
 * JDK动态代理:是通过被代理对象实现的接口产生其代理对象
 * 1:创建一个类,实现InvocationHandler接口,重写invoke方法
 * 2:在类中定义一个Object类型的变量,用于传递被代理对象,并提供这个变量的有参构造器,用于将被代理对象传递进来
 * 3:创建getProxy方法,用于创建并返回代理对象
 * */
public class JDKMyDynamicProxy implements InvocationHandler {
 
    //被代理对象
    private Object obj;
    public JDKMyDynamicProxy(Object obj) {
        this.obj = obj;
    }
 
    //产生代理对象,返回代理对象
    public Object getProxy(){
        //1、获取被代理对象的类加载器
        ClassLoader classLoader = obj.getClass().getClassLoader();
        //2、获取被代理对象的类所实现的接口
        Class<?>[] interfaces = obj.getClass().getInterfaces();
        //3、产生代理对象(通过被代理对象的类加载器及实现的接口)
        //第一个参数:被代理对象的类加载器
        //第二个参数:被代理对象实现的接口
        //第三个参数:使用产生的代理对象调用方法时,用于拦截方法执行的处理器
        Object proxy = Proxy.newProxyInstance(classLoader, interfaces,this);
        return proxy;
    }
 
 
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        begin();
        Object returnValue = method.invoke(obj,args);//执行method方法(入参)
        commit();
        return returnValue;
    }
    public void begin(){
        System.out.println("~~~~~~~开启事务");
    }
    public void commit(){
        System.out.println("~~~~~~~提交事务");
    }
 
}
 


测试类:

package com.liguoqing.test;

import com.liguoqing.dao.BookDAOImpl;
import com.liguoqing.dao.GenaralDAO;
import com.liguoqing.dao.JDKMyDynamicProxy;
import com.liguoqing.dao.StudentDAOImpl;

public class TestDynamicProxy {
   public static void main(String[] args) {
       //被代理对象
       BookDAOImpl bookDAO = new BookDAOImpl();
       StudentDAOImpl studentDAO = new StudentDAOImpl();

       //创建动态代理类对象,并将被代理对象传递到代理类中,赋值给obj
       JDKMyDynamicProxy jdkMyDynamicProxy = new JDKMyDynamicProxy(studentDAO);

       //proxy就是产生的代理对象,产生的代理对象可以强转成被代理对象实现的接口类型
       GenaralDAO proxy = (GenaralDAO) jdkMyDynamicProxy.getProxy();

       //使用代理对象调用方法,并不会执行调用的方法,而是进入到创建代理对象时指定的InvocationHandler类中的invoke方法
       //调用的方法作为一个Method参数,传递给了invoke方法
       proxy.delete();

   }
}

4.3.2 CGLib动态代理(被代理对象未实现接口)

由于JDK动态代理时通过被代理类实现的接口来创建代理对象的,因此JDK动态代理只能代理实现了接口的类对象。如果一个类没有实现任何接口,该如何产生代理对象呢?——CGLib动态代理

CGLib动态代理,是通过创建被代理类的子类来创建代理对象的,因此即使没有实现任何接口的类也可以通过CGLib产生代理对象

CGLib动态代理不能为final修饰的类创建代理对象

  • 添加CGLib的依赖
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>
 
  • CGLib动态代理代码实现
package com.liguoqing.dao;
 
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
 
import java.lang.reflect.Method;
 
/**
 * 1:添加cglib依赖
 * 2:创建一个类,实现MethodInterceptor接口,同时实现接口中的intercept方法
 * 3:在类中定义一个Object类型的变量,并提供这个变量的有参构造器,用于传递被代理对象
 * 4:定义getProxy方法创建并返回代理对象(代理对象是通过创建被代理类的子类来创建的)
 * */
 
public class CGLibDynamicProxy implements MethodInterceptor {
 
    private Object obj;
 
    public CGLibDynamicProxy(Object obj) {
        this.obj = obj;
    }
 
    public Object getProxy(){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(obj.getClass());
        enhancer.setCallback(this);
        Object proxy = enhancer.create();
        return proxy;
    }
 
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        begin();
        Object returnValue = method.invoke(obj,objects);//通过反射调用被代理类的方法
        commit();
        return returnValue;
    }
    public void begin(){
        System.out.println("~~~~~~~开启事务");
    }
    public void commit(){
        System.out.println("~~~~~~~提交事务");
    }
}


测试类:




package com.liguoqing.test;

import com.liguoqing.dao.*;

public class TestDynamicProxy {
   public static void main(String[] args) {
       //创建被代理对象
       BookDAOImpl bookDAO = new BookDAOImpl();
       StudentDAOImpl studentDAO = new StudentDAOImpl();
       
       //通过cglib动态代理类创建代理对象
       CGLibDynamicProxy cgLibDynamicProxy = new CGLibDynamicProxy(bookDAO);
       //代理对象实际上是被代理对象子类,因此代理对象可以直接强转为被代理类类型
       BookDAOImpl proxy = (BookDAOImpl)cgLibDynamicProxy.getProxy();

       //使用代理对象调用方法,实际上并没有执行这个方法,而是执行了代理类中的intercept方法,将当前调用的方法以及方法中的参数
       //传递到intercept方法
       proxy.update();

   }
}

----64

五、SpringAOP

5.1 AOP 概念

Aspect Oriented Programming 面向切面编程,是一种利用"横切"的技术(底层实现就是动态代理),对原有的业务逻辑进行拦截,并且可以在这个拦截的横切面上添加特定的业务逻辑,对原有的业务进行增强。

———

基于动态代理,实现在不改变原有业务的情况下对业务逻辑进行增强

https://note.youdao.com/yws/public/resource/f0a01c0265c577e77f3856baa78d2dce/xmlnote/F77F052DB30D4ED5A379E8C889CA60D4/14648

5.2 SpringAOP框架部署

5.2.1 创建Maven项目

5.2.2 添加依赖

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BYaQk0Ko-1651847267988)(E:\typora图片文件\image-20220424100039908.png)]

  • context

  • aspects

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.12.RELEASE</version>
</dependency>
 
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.2.12.RELEASE</version>
</dependency>

5.2.3 创建Spring配置文件

  • 需要引入aop的命名空间
<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:aop="http://www.springframework.org/schema/aop"
        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">
</beans>

5.3 AOP配置——基于XML

在DAO的方法前后添加开启事务和提交事务的逻辑

5.3.1 创建一个类,定义要添加的业务逻辑

public class TxManager {
 
    public void begin(){
        System.out.println("______开启事务");
    }
    public void commit(){
        System.out.println("______提交事务");
    } 
}

5.3.2 配置AOP

https://note.youdao.com/yws/public/resource/f0a01c0265c577e77f3856baa78d2dce/xmlnote/F77F052DB30D4ED5A379E8C889CA60D4/14648

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W8gpXFE2-1651847267991)(E:\typora图片文件\image-20220424101237342.png)]

<?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:aop="http://www.springframework.org/schema/aop"
        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">
 
    <bean id="bookDAO" class="com.liguoqing.dao.BookDAOImpl"></bean>
    <bean id="studentDAO" class="com.liguoqing.dao.StudentDAOImpl"></bean>
 
    <bean id="txManager" class="com.liguoqing.utils.TxManager"></bean>
    <aop:config>
<!--        声明切入点-->
        <aop:pointcut id="book_all" expression="execution(* com.liguoqing.dao.*.*(..))"/>
<!--        声明txManager为切面类-->
        <aop:aspect ref="txManager">
<!--            通知-->
            <aop:before method="begin" pointcut-ref="book_all"/>
            <aop:after method="commit" pointcut-ref="book_all"/>
        </aop:aspect>
    </aop:config>
 
 
</beans>

AOP开发步骤:

  1. 创建切面类,在切面类定义切面方法

  2. 将切面类配置给Spring容器

  3. 声明切入点

  4. 配置AOP通知策略

5.4 切入点的声明

5.4.1 各种切入点声明方式

<!--        使用aop:pointcut声明切入点;切入点可以是一个方法,-->
        <aop:pointcut id="book-insert" expression="execution(* com.liguoqing.dao.BookDAOImpl.insert())"/>
<!--        BookDAOImpl类中所有无参数无返回值的方法-->
        <aop:pointcut id="book_pc1" expression="execution(void com.liguoqing.dao.BookDAOImpl.*())"/>
        <!--        BookDAOImpl类中所有无返回值的方法(对参数无要求)-->
        <aop:pointcut id="book_pc2" expression="execution(void com.liguoqing.dao.BookDAOImpl.*(..))"/>
        <!--        BookDAOImpl类中所有无参数的方法(对返回值无要求)-->
        <aop:pointcut id="book_pc3" expression="execution(* com.liguoqing.dao.BookDAOImpl.*())"/>
        <!--        BookDAOImpl类中所有的方法(对参数、返回值都无要求)-->
        <aop:pointcut id="book_pc4" expression="execution(* com.liguoqing.dao.BookDAOImpl.*(..))"/>
        <!--        dao包中所有类中的所有方法(对参数、返回值都无要求)-->
        <aop:pointcut id="pc5" expression="execution(* com.liguoqing.dao.*.*(..))"/>
        <!--        dao包中所有类中的insert方法(对参数、返回值都无要求)-->
        <aop:pointcut id="pc6" expression="execution(* com.liguoqing.dao.*.insert(..))"/>
        <!--        dao包中所有类中的方法(对参数、返回值都无要求)-->
        <aop:pointcut id="pc7" expression="execution(* *(..))"/>

5.4.2 AOP使用注意事项

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QdwSPAkQ-1651847267992)(E:\typora图片文件\image-20220424103042399.png)]

        //如果要使用Spring aop面向切面编程,调用切入点方法的对象必须通过Spring容器获取
        //如果一个类中的方法被声明为切入点并织入了切点之后,通过Spring容器获取该类对象,实则获取到的是一个代理对象,
        //如果一个类中的方法没有被声明为切入点,通过Spring容器获取的就是这个类真是创建的对象
//        BookServiceDAOImpl bookServiceDAO = new BookServiceDAOImpl();
        BookServiceDAOImpl bookServiceDAO = (BookServiceDAOImpl) context.getBean("bookService");
        bookServiceDAO.addBook();

5.5 AOP通知策略

AOP通知策略:就是声明将切面类中的切点方法如何织入到切入点

  • before

  • after

  • after-throwing

  • after-returning

  • around

5.5.1 定义切面类(通知5是一个固定的写)

package com.liguoqing.utils;
 
import org.aspectj.lang.ProceedingJoinPoint;
 
public class MyAspect {
 
    public void method1(){
        System.out.println("~~~~~~~~~~~~~method1");
    }
    public void method2(){
        System.out.println("~~~~~~~~~~~~~method2");
    }
    public void method3(){
        System.out.println("~~~~~~~~~~~~~method3");
    }
    public void method4(){
        System.out.println("~~~~~~~~~~~~~method4");
    }
    //环绕通知的方法,必须遵守如下的定义规则
    //1:必须带有一个ProceedingJoinPoint类型的参数,
    //2:必须有Object类型的返回值
    //3:在前后增强的业务逻辑之间执行Object v = point.proceed();
    //4: 方法最后返回 return v;
    public Object method5(ProceedingJoinPoint point) throws Throwable {
        System.out.println("~~~~~~~~~~~~~method5----before");
        //此句代码的执行就表示切入点方法的执行
        Object v = point.proceed();
        System.out.println("~~~~~~~~~~~~~method5----after");
        return v;
    }
 
}

5.5.2 配置切面类(5种不同的通知)

<?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:aop="http://www.springframework.org/schema/aop"
        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">
 
 
    <bean id="myAspect" class="com.liguoqing.utils.MyAspect"></bean>
 
    <aop:config>
    
        <!--        使用aop:pointcut声明切入点;切入点可以是一个方法,-->
        <aop:pointcut id="book-insert" expression="execution(* com.liguoqing.dao.BookDAOImpl.insert())"/>
 
        <!-- 切面类  -->
        <aop:aspect ref="myAspect">
<!--            aop:before 前置通知,切入到指定切入点之前-->
            <aop:before method="method1" pointcut-ref="book-insert"/>
<!--            aop:after 后置通知,切入到指定切入点之后-->
            <aop:after method="method2" pointcut-ref="book-insert"/>
<!--            aop:after-throwing 异常通知,切入点抛出异常之后-->
            <aop:after-throwing method="method3" pointcut-ref="book-insert"/>
<!--            aop:after-returning 方法返回值返回之后,对于一个java方法而言return返回值也是方法的一部分
                因此”方法返回值返回之后“和”方法执行结束“是同一个时间点,所以after和after-returning根据配置的顺序决定执行的顺序-->
            <aop:after-returning method="method4" pointcut-ref="book-insert"/>
<!--            aop:around 环绕通知-->
            <aop:around method="method5" pointcut-ref="book-insert"/>
        </aop:aspect>
        
    </aop:config>
 
</beans>

六、SpringAOP注解配置

6.1 Spring AOP注解配置框架部署

6.1.1 创建Maven工程

6.1.2 添加Spring依赖

  • context

  • aspects

6.1.3 Spring配置文件

<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:aop="http://www.springframework.org/schema/aop"
        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">
 <!--基于注解配置的ioc代理-->
    <context:annotation-config/>
    
    <context:component-scan base-package="com.liguoqing"/>
    
<!--基于注解配置的AOP代理-->
    <aop:aspectj-autoproxy/>
 
 
 
</beans>

6.2 AOP注解配置案例

package com.liguoqing.utils;
 
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
 
@Component
//切面类
@Aspect
public class TransactionManager {
     //切入点
    @Pointcut("execution(* com.liguoqing.dao.*.*(..))")
    //pc1相当于切入点的id
    public void pc1(){
 
    }
//通知
    @Before("pc1()")
    public void begin(){
        System.out.println("~~~开启事务");
    }
    @After("pc1()")
    public void commit(){
        System.out.println("~~~提交事务");
    }
 
    @Around("pc1()")
    public Object printExecuteTime(ProceedingJoinPoint point) throws Throwable {
 
        long time1 = System.currentTimeMillis();
        Object v = point.proceed();
        long time2 = System.currentTimeMillis();
        System.out.println("~~~time:" + (time2 - time1));
        return v;
 
    }
 
}
 
 

注意:注解使用虽然方便,但是只能在源码上添加注解,因此我们的自定义类提倡使用注解配置,但是如果使用到第三方提供的类则需要通过XML配置形式完成配置。

—70

七、Spring整合MyBatis

Spring两大核心思想:IoC和AOP

IoC:控制反转,Spring容器可以完成对象的创建、属性注入、对象管理等工作

AOP:面向切面,在不修改原有业务逻辑的情况下,实现原有业务的增强

7.1 Spring可以对MyBatis提供哪些支持?

  • IoC支持:SpringIoC可以为MyBatis完成DataSource、SqlSessionFactory、SqlSession、DAO对象的创建

  • AOP支持:使用Spring提供的事务管理切面类完成对MyBatis数据库操作中的事务管理

7.2 Spring整合MyBatis准备工作

7.2.1 创建Maven工程

7.2.2 部署MyBatis框架:

  • 添加依赖

  • Mysql驱动(mysql-connector-java)

  • MyBatis(mybatis)

<!--MyBatis依赖-->
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>
 
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
  • 创建 MyBatis配置文件,配置文件里无需进行任何配置:mybatis-config.xml
<?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>
 
</configuration>

7.2.3 部署Spring框架

  • 添加依赖
<!--        Spring依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.12.RELEASE</version>
</dependency>
 
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.2.12.RELEASE</version>
</dependency>
<!--  要让spring支持mybatis持久化支持的依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.12.RELEASE</version>
</dependency>
  • 创建Spring配置文件:applicationContext.xml
<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:aop="http://www.springframework.org/schema/aop"
        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">
</beans>

7.2.4 添加Spring整合MyBatis的依赖

  • mybatis-spring 就是mybatis提供的兼容Spring的补丁
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.2</version>
</dependency>
 

7.2.5 spring mybatis druid spring-mybatis整合的pom.xml

<?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.qfedu</groupId>
    <artifactId>spring-mybatis</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
<!--        mybatis-->

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>


        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>

<!--      druid  -->

        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>

<!--        spring-->
        <!--       context Spring-ioc依赖-->
        <!--       context和aspects  Spring-aop依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.12.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.12.RELEASE</version>
        </dependency>
<!--  要让spring支持mybatis持久化支持的依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.12.RELEASE</version>
        </dependency>

        <!--        spring-mybatis-->
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>
    </dependencies>
</project>

7.3 Spring整合MyBatis整合配置

7.3.1 整合Druid连接池

  • 添加druid的依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
</dependency>
 
  • 创建druid.properties属性文件(druid.properties)
druid.driver=com.mysql.cj.jdbc.Driver
druid.url=jdbc:mysql://localhost:3306/db_2010_mybatis?characterEncoding = utf-8
druid.username=root
druid.password=123456
 
 
#连接池参数
#init:初始连接数  minIdle:最小连接数 maxActive:最大连接数 timeout:超时时间
druid.pool.init = 3
druid.pool.minIdle = 5
druid.pool.maxActive = 20
druid.pool.timeout = 30
  • 在applicationContext.xml中配置DruidDataSource
<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:aop="http://www.springframework.org/schema/aop"
        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">
 
<!--加载druid.properties属性文件-->
    <context:property-placeholder location="classpath:druid.properties"/>
 
<!--依赖Spring容器完成数据源DataSource的创建-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${druid.driver}"/>
        <property name="url" value="${druid.url}"/>
        <property name="username" value="${druid.username}"/>
        <property name="password" value="${druid.password}"/>
 
        <property name="initialSize" value="${druid.pool.init}"/>
        <property name="minIdle" value="${druid.pool.minIdle}"/>
        <property name="maxActive" value="${druid.pool.maxActive}"/>
        <property name="maxWait" value="${druid.pool.timeout}"/>
 
    </bean>
</beans>

7.3.2 整合MyBatis–创建SqlSessionFactory

相当于mybatis的mybatis-config.xml和MybatisUtils.java

依赖Spring容器完成MyBatis的SqlSessionFactory对象的创建

注意:

driver

    <!--bean-->
    <bean id="driver" class="com.mysql.jdbc.Driver"/>
<!--    druidDateSource-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driver" ref="driver"/>  这个driver需要一个类   
    <property name="driverClassName" value="${druid.driver}"/>  这个driverName只需要一个字符串
    <property name="url" value="${druid.url}"/>
    <property name="username" value="${druid.username}"/>
    <property name="password" value="${druid.password}"/>


    <property name="initialSize" value="${druid.pool.init}"/>
    <property name="minIdle" value="${druid.pool.minIdle}"/>
    <property name="maxActive" value="${druid.pool.maxActive}"/>
    <property name="maxWait" value="${druid.pool.timeout}"/>
</bean>
<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:aop="http://www.springframework.org/schema/aop"
        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">

<!-- bean ,context,aop   -->

    <!--context-->
    <!--加载druid.properties属性文件-->
    <context:property-placeholder location="druid.properties"/>

<!-- =======================================================================-->

    <!--bean-->
<!--    druidDateSource-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${druid.driver}"/>
    <property name="url" value="${druid.url}"/>
    <property name="username" value="${druid.username}"/>
    <property name="password" value="${druid.password}"/>


    <property name="initialSize" value="${druid.pool.init}"/>
    <property name="minIdle" value="${druid.pool.minIdle}"/>
    <property name="maxActive" value="${druid.pool.maxActive}"/>
    <property name="maxWait" value="${druid.pool.timeout}"/>
</bean>

<!--   PooledDataSource -->
<!--<bean id="dataSource" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
    <property name="driver" value="${driver}"/>
    <property name="url" value="${url}"/>
    <property name="username" value="${username}"/>
    <property name="password" value="${password}"/>
</bean>-->

    <!--        相当于MybatisUtils  -->

    <!--依赖Spring容器完成MyBatis的SqlSessionFactory对象的创建-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

<!--                相当于mybatis-config.xml  -->


        <!--        配置数据源-->
        <property name="dataSource" ref="druidDataSource"/>
        <!--        配置mapper文件的路径-->
        <property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/>
        <!--        可选,配置需要定义别名的实体类的包-->
        <property name="typeAliasesPackage" value="com.liguoqing.pojo"/>
        <!--        可选,配置MyBatis的主配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>
    <!-- =======================================================================-->
    <!--aop-->


</beans>

7.3.3 整合MyBatis-创建Mapper

<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:aop="http://www.springframework.org/schema/aop"
        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">
 
    <!--加载druid.properties属性文件-->
    <context:property-placeholder location="classpath:druid.properties"/>
 
    <!--依赖Spring容器完成数据源DataSource的创建-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${druid.driver}"/>
        <property name="url" value="${druid.url}"/>
        <property name="username" value="${druid.username}"/>
        <property name="password" value="${druid.password}"/>
 
        <property name="initialSize" value="${druid.pool.init}"/>
        <property name="minIdle" value="${druid.pool.minIdle}"/>
        <property name="maxActive" value="${druid.pool.maxActive}"/>
        <property name="maxWait" value="${druid.pool.timeout}"/>
 
    </bean>
 
    <!--依赖Spring容器完成MyBatis的SqlSessionFactory对象的创建-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--        配置数据源-->
        <property name="dataSource" ref="druidDataSource"/>
<!--        配置mapper文件的路径-->
        <property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/>
<!--        可选,配置需要定义别名的实体类的包-->
        <property name="typeAliasesPackage" value="com.liguoqing.pojo"/>
<!--        可选,配置MyBatis的主配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>
--------------------------------------------------------------------------------------------------------
    <!--加载dao包中的所有DAO接口,通过sqlSessionFactory获取sqlSession,然后创建所有的DAO接口对象,存储在Spring容器-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="basePackage" value="com.liguoqing.dao"/>
    </bean>
 
</beans>

7.4 Spring整合MyBatis整合AOP配置

使用Spring提供的事务管理切面类完成DAO中增删该操作的事务管理

–77集

<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: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:annotation-config/>
<!--注解需要扫描的包-->
    <context:component-scan base-package="com.liguoqing"/>
    
    <!--加载druid.properties属性文件-->
    <context:property-placeholder location="classpath:druid.properties"/>
 
    <!--依赖Spring容器完成数据源DataSource的创建-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${druid.driver}"/>
        <property name="url" value="${druid.url}"/>
        <property name="username" value="${druid.username}"/>
        <property name="password" value="${druid.password}"/>
 
        <property name="initialSize" value="${druid.pool.init}"/>
        <property name="minIdle" value="${druid.pool.minIdle}"/>
        <property name="maxActive" value="${druid.pool.maxActive}"/>
        <property name="maxWait" value="${druid.pool.timeout}"/>
 
    </bean>
 
    <!--依赖Spring容器完成MyBatis的SqlSessionFactory对象的创建-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--        配置数据源-->
        <property name="dataSource" ref="druidDataSource"/>
<!--        配置mapper文件的路径-->
        <property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/>
<!--        可选,配置需要定义别名的实体类的包-->
        <property name="typeAliasesPackage" value="com.liguoqing.pojo"/>
<!--        可选,配置MyBatis的主配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>
--------------------------------------------------------------------------------------------------------------------------------
    <!--加载dao包中的所有DAO接口,通过sqlSessionFactory获取sqlSession,然后创建所有的DAO接口对象,存储在Spring容器-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="basePackage" value="com.liguoqing.dao"/>
    </bean>
 
    <!--1:将Spring提供的事务管理类配置给Spring容器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="druidDataSource"/>
    </bean>
    <!--2:通过Spring jdbc提供的tx标签,声明事务管理策略-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="insert*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
            <tx:method name="query*" isolation="REPEATABLE_READ" propagation="SUPPORTS"/>
        </tx:attributes>
    </tx:advice>
 
 
</beans>

7.4.1 事务的隔离级别

isolation :设置事务隔离级别:
READ_UNCOMMITTED:(读未提交:事务1在执行的过程中,事务2可以读也可以写,
事务1可以读取到事务2提交的数据(脏读)(不可重复读)(幻读)),

READ_COMMITTED:(读已提交:事务1在执行的过程中,事务2可以读也可以写,
但是事务1只能读取到事务2提交后的数据(不可重复读)(幻读)),

REPEATABLE_READ:(可重复读:在事务1执行过程中,事务2只能读但是不能改,
事务2可以添加数据(幻读))

SERIALIZABLE(效率低但是很安全):(串行化:事务1在执行过程中,
事务2既不能读也不能写)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GuicWpmd-1651847267993)(E:\typora图片文件\image-20220425145712716.png)]

7.4.2 事务的传播机制

propagation: 设置事务的传播机制:

    REQUIRED:如果上层方法没有事务,则创建一个新的事务,如果已经存在事务,则加入到事务中。
    
    SUPPORTS:如果上层方法没有事务,则以非事务方式执行。如果已经存在事务,则加入到事务中。
   
    REQUIRES_NEW  :如果上层方法没有事务,则创建一个新的事务,如果已经存在事务,则将当前事务挂起,自己创建一个新的事务去执行(老子一直要用新事务)。
    
    NOT_SUPPORTED:如果上层方法没有事务,则以非事务方式执行,如果已经存在事务,则将当前事务挂起(死都不用事务)。
    
    NEVER:如果上层方法没有事务,则以非事务方式执行,如果已经存在事务,则将抛出异常(死都不用事务,要是有事务我就抛异常)。
    
    MANDATORY:如果上层方法已经存在事务,则加入到事务中执行,如果不存在事务则抛出异常。
    
    NESTED:如果上层方法没有事务,则创建一个新的事务,如果已经存在事务,则嵌套到事务中。

7.4.3 Spring AOP事务管理配置——xml配置

<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: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:annotation-config/>
<!--注解需要扫描的包-->
    <context:component-scan base-package="com.liguoqing"/>
    
    <!--加载druid.properties属性文件-->
    <context:property-placeholder location="classpath:druid.properties"/>
 
    <!--依赖Spring容器完成数据源DataSource的创建-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${druid.driver}"/>
        <property name="url" value="${druid.url}"/>
        <property name="username" value="${druid.username}"/>
        <property name="password" value="${druid.password}"/>
 
        <property name="initialSize" value="${druid.pool.init}"/>
        <property name="minIdle" value="${druid.pool.minIdle}"/>
        <property name="maxActive" value="${druid.pool.maxActive}"/>
        <property name="maxWait" value="${druid.pool.timeout}"/>
 
    </bean>
 
    <!--依赖Spring容器完成MyBatis的SqlSessionFactory对象的创建-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--        配置数据源-->
        <property name="dataSource" ref="druidDataSource"/>
<!--        配置mapper文件的路径-->
        <property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/>
<!--        可选,配置需要定义别名的实体类的包-->
        <property name="typeAliasesPackage" value="com.liguoqing.pojo"/>
<!--        可选,配置MyBatis的主配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>
---------------------------------------------------------------------------------------------
    <!--加载dao包中的所有DAO接口,通过sqlSessionFactory获取sqlSession,然后创建所有的DAO接口对象,存储在Spring容器-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="basePackage" value="com.liguoqing.dao"/>
    </bean>
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    <!--1:将Spring提供的事务管理类配置给Spring容器-->
    <bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="druidDataSource"/>
    </bean>
    
    <!--2:通过Spring jdbc提供的tx标签,声明事务管理策略-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
<!-- isolation 设置事务隔离级别:
        READ_UNCOMMITTED(读未提交:事务1在执行的过程中,事务2可以读也可以写,事务1可以读取到事务2提交的数据(脏读)(不可重复读)(幻读)),
        READ_COMMITTED(读已提交:事务1在执行的过程中,事务2可以读也可以写,但是事务1只能读取到事务2提交后的数据(不可重复读)),
        REPEATABLE_READ(可重复读:在事务1执行过程中,事务2只能读但是不能改,事务2可以添加数据(幻读))
        SERIALIZABLE(串行化:事务1在执行过程中,事务2既不能读也不能写)
 
     propagation: 设置事务的传播机制:
         REQUIRED:如果上层方法没有事务,则创建一个新的事务,如果已经存在事务,则加入到事务中。
         SUPPORTS: 如果上层方法没有事务,则以非事务方式执行。如果已经存在事务,则加入到事务中。
         REQUIRES_NEW:如果上层方法没有事务,则创建一个新的事务,如果已经存在事务,则将当前事务挂起,自己创建一个新的事务去执行(老子一直要用新事务)。
         NOT_SUPPORTED:如果上层方法没有事务,则以非事务方式执行,如果已经存在事务,则将当前事务挂起(死都不用事务)。
         NEVER:如果上层方法没有事务,则以非事务方式执行,如果已经存在事务,则将抛出异常(死都不用事务,要是有事务我就抛异常)。
         MANDATORY:如果上层方法已经存在事务,则加入到事务中执行,如果不存在事务则抛出异常。
         NESTED:如果上层方法没有事务,则创建一个新的事务,如果已经存在事务,则嵌套到事务中。
          -->
            <tx:method name="insert*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
            <tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
            <tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
            <tx:method name="query*" isolation="REPEATABLE_READ" propagation="SUPPORTS"/>
        </tx:attributes>
    </tx:advice>
    
    <!--3、将事务管理策略以AOP配置,应用于DAO操作方法-->
    <aop:config>
        <aop:pointcut id="crud" expression="execution(* com.liguoqing.service.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="crud"/>
    </aop:config>
 
</beans>

7.4.4 Spring AOP事务管理配置——注解配置

  • applicationContext.xml 配置事务管理类,声明使用注解方式进行事务配置
<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: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:annotation-config/>
<!--注解需要扫描的包-->
    <context:component-scan base-package="com.liguoqing"/>
    
    <!--加载druid.properties属性文件-->
    <context:property-placeholder location="classpath:druid.properties"/>
 
    <!--依赖Spring容器完成数据源DataSource的创建-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${druid.driver}"/>
        <property name="url" value="${druid.url}"/>
        <property name="username" value="${druid.username}"/>
        <property name="password" value="${druid.password}"/>
 
        <property name="initialSize" value="${druid.pool.init}"/>
        <property name="minIdle" value="${druid.pool.minIdle}"/>
        <property name="maxActive" value="${druid.pool.maxActive}"/>
        <property name="maxWait" value="${druid.pool.timeout}"/>
 
    </bean>
 
    <!--依赖Spring容器完成MyBatis的SqlSessionFactory对象的创建-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--        配置数据源-->
        <property name="dataSource" ref="druidDataSource"/>
<!--        配置mapper文件的路径-->
        <property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/>
<!--        可选,配置需要定义别名的实体类的包-->
        <property name="typeAliasesPackage" value="com.liguoqing.pojo"/>
<!--        可选,配置MyBatis的主配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>
 
    <!--加载dao包中的所有DAO接口,通过sqlSessionFactory获取sqlSession,然后创建所有的DAO接口对象,存储在Spring容器-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="basePackage" value="com.liguoqing.dao"/>
    </bean>
 
    <!--1:将Spring提供的事务管理类配置给Spring容器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="druidDataSource"/>
    </bean>
-----------------------------------------------------------
<!--    2:声明使用注解完成事务配置-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
-------------------------------------------------------------------------------------
 
    <!--2:通过Spring jdbc提供的tx标签,声明事务管理策略
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="insert*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
            <tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
            <tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
            <tx:method name="query*" isolation="REPEATABLE_READ" propagation="SUPPORTS"/>
        </tx:attributes>
    </tx:advice>-->
 
    <!--3、将事务管理策略以AOP配置,应用于DAO操作方法-->
    <!-- 事务最好加在services上-->
    <aop:config>
        <aop:pointcut id="crud" expression="execution(* com.liguoqing.service.*.*(..))"/>
        
          <!-- 切面类  -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="crud"/>
    </aop:config>
 
</beans>

<aop:config>
<aop:pointcut id=“crud” expression=“execution(* com.liguoqing.service..(…))”/>

  • 在需要Spring进行事务管理的方法上添加 @Transactional 注解
package com.liguoqing.service.impl;
 
import com.liguoqing.service.UserService;
import com.liguoqing.dao.UserDAO;
import com.liguoqing.pojo.User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
 
import javax.annotation.Resource;
import java.util.List;
 
@Service
public class UserServiceImpl implements UserService {
 
    @Resource
    private UserDAO userDAO;
 
    @Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.SUPPORTS)
    public List<User> listUser() {
        return userDAO.queryUsers();
    }
}

—————————————————————————————————
" value=“sqlSessionFactory”/>

<!--1:将Spring提供的事务管理类配置给Spring容器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="druidDataSource"/>
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>

<!--2:通过Spring jdbc提供的tx标签,声明事务管理策略
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="insert*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
        <tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
        <tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
        <tx:method name="query*" isolation="REPEATABLE_READ" propagation="SUPPORTS"/>
    </tx:attributes>
</tx:advice>-->

<!--3、将事务管理策略以AOP配置,应用于DAO操作方法-->
<!-- 事务最好加在services上-->
<aop:config>
    <aop:pointcut id="crud" expression="execution(* com.liguoqing.service.*.*(..))"/>
    
      <!-- 切面类  -->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="crud"/>
</aop:config>
```

<aop:config>
<aop:pointcut id=“crud” expression=“execution(* com.liguoqing.service..(…))”/>

  • 在需要Spring进行事务管理的方法上添加 @Transactional 注解
package com.liguoqing.service.impl;
 
import com.liguoqing.service.UserService;
import com.liguoqing.dao.UserDAO;
import com.liguoqing.pojo.User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
 
import javax.annotation.Resource;
import java.util.List;
 
@Service
public class UserServiceImpl implements UserService {
 
    @Resource
    private UserDAO userDAO;
 
    @Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.SUPPORTS)
    public List<User> listUser() {
        return userDAO.queryUsers();
    }
}

—————————————————————————————————

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Security是一个强大的身份验证和授权框架,用于保护Spring应用程序的安全性。下面是Spring Security的基础用法和一些常见知识点的详解: 1. 配置Spring Security:在Spring项目,需要添加Spring Security的依赖,并配置相应的安全配置类(继承自 `WebSecurityConfigurerAdapter`),通过重写方法来配置身份验证和授权规则。 2. 身份验证(Authentication):Spring Security提供了多种身份验证方式,包括基于表单、HTTP基本认证、OAuth等。可以通过配置认证提供者(Authentication Provider)来定义如何验证用户的身份。 3. 授权(Authorization):通过配置访问控制规则,可以限制用户对特定资源的访问权限。Spring Security提供了多种授权方式,如基于角色、权限、表达式等。 4. 用户和角色管理:Spring Security可以与数据库或其他存储系统集成,用于管理用户信息和角色。可以自定义用户详细信息服务(UserDetailsService)和密码编码器(PasswordEncoder)来获取用户信息和验证密码。 5. 登录和注销:通过配置登录页面和注销功能,用户可以进行登录和退出操作。Spring Security提供了默认的登录页面和注销处理,也可以自定义实现。 6. CSRF防护:Spring Security默认开启CSRF(跨站请求伪造)防护功能,可以防止恶意网站利用用户的身份发起跨站请求。可以通过配置全局或特定URL的CSRF保护。 7. Remember-Me功能:Spring Security提供了Remember-Me功能,允许用户在下次访问时自动登录。可以通过配置持久化令牌的方式实现。 8. 安全事件和日志:Spring Security可以记录安全相关的事件和日志,包括认证成功、失败、访问被拒绝等。可以通过自定义的 `ApplicationListener` 或配置日志记录器来处理和记录这些事件。 9. 自定义过滤器和拦截器:通过自定义过滤器或拦截器,可以在请求处理过程添加额外的安全逻辑。Spring Security提供了多个预定义的过滤器和拦截器,也可以自定义实现。 10. 方法级安全性:Spring Security支持方法级别的安全性控制,可以通过注解(如 `@Secured`、`@PreAuthorize`)或表达式(如 `hasRole()`、`hasPermission()`)来限制方法的访问权限。 11. 扩展和定制:Spring Security提供了丰富的扩展点,可以根据需求进行定制开发。例如,自定义认证提供者、用户详细信息服务、访问决策管理器等。 这些是Spring Security的基础用法和常见知识点的概述。具体使用时,可以根据项目需求和实际情况进行配置和定制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值