Spring框架

本文深入探讨Spring框架的核心特性,包括IOC(控制反转)和DI(依赖注入)的概念与实现,基于配置文件和注解的ID管理,以及AOP(面向切面编程)的应用。同时,讲解了Spring集成MyBatis的过程,并讨论了事务管理,特别是Spring的声明式事务管理。最后,简述了Spring在Web项目中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为了解耦合:让类与类、模块与模块之间关系更松散
spring适合管理哪些对象:service对象、dao对象、工具类对象
spring不适合管理哪些对象:实体类、(servlet、listener、filter等web对象也不适合,因为这些对象是给tomcat创建和管理的)

spring又叫容器,是装Java对象。可以控制spring创建Java对象、给属性赋值

可以当作容器的对象---tomcat服务器----管理servlet、listener、filter对象

手动下载对应的spring版本:https://repo.spring.io/                       //实际项目使用Maven自己会处理的
 

docs:文档
libs:源代码(spring是开源的)  //spring比较大,分成20多个独立的模块,为了方便使用每模块做成单独的jar包
        .jar                     字节码打包
        javadoc.jar        文档打包
        sources.jar        Java源代码打包
schena: spring框架使用的约束文件
        

Core Container:核心容器,包含4个模块

IOC:控制反转

是一个理论思想:把对象的创建、属性赋值、对象的生命周期都交给代码以外的容器管理
        控制:对象创建、属性赋值、对象的生命周期
        反转:开发人员管理对象的权限转移给代码之外的容器实现。由容器完成对象的管理         
        正转:开发人员 new 构造方法创建对象。由开发人掌握对象的创建、属性赋值、对象的生命周期。

开发人员通过容器可以使用容器中的对象

技术实现:DI (依赖注入)-----程序只需要提供使用对象的名字,对象如何创建、如何从容器中查找、获取都由容器内部自己实现
                                依赖:A类用了B类的内容    (执行A类的功能,需要先创建B类的对象)
                                注入:赋值                           (B类对象作为A类的属性)

Spring框架使用DI来实现IoC思想,通过名字获取容器中对应的对象(spring底层使用反射机制创建对象、给属性赋值)

IoC通过管理对象解耦合。解决处理业务逻辑对象之间的耦合关系,也就是service对象和dao对象

使用:     1.使用maven创建普通的Java项目后,修改pom.xml文件加入spring依赖Spring-context       //依赖代码去Maven官网找
                2.开发人员写自己的业务代码(类)
                3.创建spring配置文件xml(声明对象:一个<bean>表示一个Java对象)把对象交给spring创建和管理
                4.创建spring容器对象ApplicationContext接口//代表配置文件,从容器对象中根据名称获取对象getBean("id值")

 

spring配置文件一般会起名beans.xml 或applicationContext.xml 

<?xml version="1.0" encoding="UTF-8"?>
<!--beans根标签
    跟标签后面的属性是约束文件的说明
    xmls                  声明命名空间
    xmlns:xsi             命名xsi空间
    xsi:schemaLocation    xsi空间里有个标签schemaLocation  
    http://www.springframework.org/schema/beans     约束文件的具体路径
    http://www.springframework.org/schema/beans/spring-beans.xsd   互联网上的约束文件的地址
 -->
<beans xmlns="http://www.springframework.org/schema/beans"          
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--声明对象
            bean标签:spring管理的java对象
                id:自定义的对象名
                class:全类名,通过反射创建对象用的
            spring根据id、class创建对象,把对象放到spring的map对象中  //map.put(id,对象)
    -->        
    <bean id="对象名" class="全类名">    

    
</beans>

        /*1.指定spring的配置文件路径,从类路径classes下,因为代码编译后放在target/classes之下,而resources的文件也是放在这*/
        String config = "beans.xml";
        /*2.创建容器对象: ApplicationContext接口。 ClassPathXmlApplicationContext实现类,从类路径中读取配置文件*/
            //在这步时调用无参构造创建对象。即创建容器对象时读取配置文件,创建文件中的所有的声明对象<bean>,然后放到容器的map中
            //好处是以后用的时候因为容器中已经有对象了,所以获取速度快。缺点是可能浪费性能
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);       
        /*3.从容器中获取指定名称的对象(bead中的id值),类型为Object,需要转回自己的类型*/
        SomeService service = (SomeService) ctx.getBean("id值");
        /*4.调用接口类型对象的方法*/
        service.doSome();



        int count = ctx.getBeanDefinitionCount();    //获取对象的数量
        String[] names = ctx.getBeanDefinitionNames(); //获取对象的名字字符串数组

        DI:给属性赋值

方式

  • 基于配置文件
  • 基于注解    

 DI分类:

  • set注入  //设值注入         spring调用无参构造方法创建对象。调用类的set方法,在set方法中完成属性赋值        //必须有set方法,本质来讲执行的是set属性名(),与属性名无关
  • 构造注入                         spring调用构造方法时完成属性赋值                                   

基于配置文件的ID: 

1.配置文件、set注入
    <bean id="" class="">
        <!--简单类型set注入 (简单类型:基本类型、String类型)-->
        <property name="属性名" value="属性值"/>                 //name值与set+属性名()方法相关,与属性无关
        <!--引用类型set注入-->
        <property name="属性名" ref="对象名,即对象的id值"/>
    </bean>


2.配置文件、构造注入
    <bean标>的<constructor-arg>:表示构造方法的1个参数
                  name:形参名
                  index:构造方法参数位置  0开始
                  value:简单类型实参
                  ref:引用类型实参
    <bean id="" class="">
        <constructor-arg name="形参名" value="简单类实参"/>         将value值赋给形参
        <constructor-arg name="形参名" ref="引用类型实参"/>
        <constructor-arg index="下标位置" value="简单类实参"/>
        <constructor-arg index="下标位置" ref="引用类型实参"/>
    </bean>


3.引用类型自动赋值:
        autowire属性:该对象的引用类型采取自动赋值
            值:byName、byType
    <bean id="" class="" autowire=""></bean>

    

引用类型的自动注入:<bean>带有属性autowire="byName或byType"

  • byName:Java类中引用类型属性名和spring容器的<bean>的id值相同、类型也相同。这样<bean>能赋值给属性               
  • byType:Java类中引用类型的数据类型和spring容器的<bean>是同源关系。这样<bean>能赋值给属性   //前提是<bean>对象只在该类型中有一个,不然类的属性就不知道赋值哪个了 
    • 同源关系: 属性的类型和<bean>的类型:相同、继承关系、接口实现

多个Spring配置文件:按功能模块分、按类的功能分

<?xml version="1.0" encoding="UTF-8"?>
<!--suppress ALL -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!--其他配置文件-->
    <import resource="classpath:其他文件的类路径"/>
    <import resource="classpath:可以同通配符*表示一段文字"/>
</beans>

基于注解的ID

创建对象的注解 (234注解都是扩展自Component注解)
        @Component                          位置:类上                        创建Java对象,相当于<bean>        
        @Repository                         位置:dao接口的类上                创建dao接口的类的对象--dao对象(持久层对象),能访问数据库  
        @Service                            位置:放在业务层接口的实现类上      创建业务层对象,业务层对象有事务的功能
        @Controller                         位置:放在控制器接口的实现类上      创建控制器对象(表示层对象),控制器对象能接受请求、把请求的处理结果显示给用户

              属性:value        表示对象的名称,即id值 //可省略value属性名、可不提供该属性,默认对象名为 类名的小驼峰形式
              @Component(value = "对象名")        @Component("对象名")        @Component

                        

属性赋值注解
        @Value              简单类型属性值                                                    位置:1)属性定义上面,无需set方法          2)set方法上面,需要set方法
                属性:value        表示简单类型属性值(可以使用属性配置文件的key-value)
                @Value(value = "属性值")        @Value("属性值")      @Value(value = "${key值}")

        
        @Autowired          引用类型属性赋值,使用自动注入原理(byName、默认byType)             位置:同上
                                                    //使用byName:再加上一个注解@Qualifier(value = "bean的id值")或@Qualifier("bean的id值")表示把该名的对象赋值给该属性
                属性:required        值为:false、true默认 (spring启动时创建容器对象会检查引用类型属性是否赋值成功,如果true会报错停止,false会是默认null不报错正常执行)
        @Resource           该注解不是Spring的,是JDK的,spring支持该注解使用。引用类型属性赋值,使用自动注入原理(默认byName、byType)        位置:同上
                //先使用byName,如果失败再使用byType
                //高于JDK1.8,JDK不带该注解,需要加入依赖:Maven中央仓库中的Javax Annotation APIJava通用注解
                属性:name        只使用byName的方式,指定对象名   @Resource(name = "bean的id值")

使用注解要在配置文件中声明组件扫描器: 框架会扫描这个包和其子包内的所有类,找到类的注解,按照注解的功能创建对象、属性赋值

<?xml version="1.0" encoding="UTF-8"?>
<!--suppress ALL -->
<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 https://www.springframework.org/schema/context/spring-context.xsd">

    <!--组件扫描器:扫描一个包-->
    <context:component-scan base-package="注解所在的包名"/>
    <!--组件扫描器:扫描多个包,所有分号、逗号、空格来分隔包-->
    <context:component-scan base-package="包名1;包名2,包名3 包名4"/>
    <!--组件扫描器:扫描多个包,使用父包-->
    <context:component-scan base-package="包名1;包名2,包名3 包名4"/>


    
    <!--在注解中读取属性配置文件:即.properties文件,这样就能在注解中使用key-value数据了-->
    <context:property-placeholder location="classpath:类路径"/>
</beans>

XML好处是代码与数据分离,方便使用
        缺点是配置文件过于繁琐,不利于开发维护
注解好处是方便开发省事可读性好
        缺点是代码与数据不分离,每次改完需要重新编译

AOP

AOP:面向切面编程:
        1)设计项目时,找出切面的功能
        2)安排切面的执行时间(目标方法执行前后)
        3)执行位置(哪个类、哪个方法增加切面)
AOP思想技术实现:1)spring框架实现类AOP思想的部分功能,但是很繁琐,一般都是框架自己用不是开发人员用
                                 2)Aspectj:独立框架(spring框架了集成该框架,通过spring可以间接用),专门做AOP

AOP是一种动态的技术思想,实现业务功能与非业务功能的解耦合,让业务功能成为独立模块,其他功能成为独立模块,达到可以复用的目的。
当目标方法不能修改时,在执行期间通过AOP技术生成代理对象,代理业务功能的同时增加功能

JoinPoint连接点:连接切面的业务方法(目标类的方法),在业务方法执行时会执行切面的功能
Pointcut切入点:一个或多个连接点的集合,                //表示位置
Advice通知/增强:在目标方法执行之前还是之后执行       // 表示时间
Aspect切面:给业务方法(目标类方法)增加的功能,一般都是非业务功能、可以复用的     //   表增加的功能
target目标对象:给哪个对象增加切面功能

动态的思想:在程序运行时,创建代理,使用代理方法增加切面功能。

Aspectj框架使用方式:1)注解         2)XML配置文件             //Maven项目中,spring继承Aspectj,只需在pom.xml中加入其依赖就可以:spring-aspectj

通知Advice:即时间方面的注解
@Before:前置通知                                                  位置:切面方法上                               //目标方法执行之前执行,不会影响目标方法的执行,不会修改目标方法的结果
                                                            (方法:public、void、可选型参1:JoinPoint类型,表示正在作用的目标方法(连接点)。相当于反射的Method。可以查看目标方法的信息
                属性:value         表示切入点表达式,来确定切面执行的位置

                        @Before(Value = "切入点表达式")

@AfterReturning:后置通知                                        位置:切面方法上                            //目标方法执行之后执行,不会影响目标方法的执行,可以获取目标方法的返回结果
                                                                                  (方法:public、void、可选型参1:JoinPoint类型、自定义形参:推荐Object类型,表示目标方法的返回值)
                属性: value                 表示切入点表达式,来确定切面执行的位置
                            returning           自定义变量,表示目标方法的返回值。必须和通知方法的形参名一致

                        @AfterReturning(Value = "切入点表达式",returning = "自定义变量名")

@Around:环绕通知                                                 位置:切面方法上                         //执行代理目标方法:执行切面方法,返回切面方法的返回值
                                                                                                                                        //切面方法里可以控制目标方法的执行:ProceedingJoinPoint对象.proceed()
                                                                                                                                        //切面方法里可以对目标方法的执行结果进行操作,任何返回想要的数据
                                                                                                                                        //切面方法里可以在目标方法执行的上下添加功能
                                                                                        (方法:public、返回值:推荐Object,表示调用目标方法希望得到的结、
    形参:ProceedingJoinPoint接口类型,
该接口继承JoinPoint接口,相当于反射中的Method,用来执行目标方法的,ProceedingJoinPoint对象.proceed()相当于method.invoke() ) 
                属性:value                 表示切入点表达式,来确定切面执行的位置

                        @Around(value = "切入点表达式")




@AfterThrowing:异常通知            //了解即可//目标方法抛出异常后执行。能获取目标方法的异常现象。不是异常处理程序,可以得到发生异常的通知,可以看作目标方法的监控程序
                                (方法:public、void、形参:Exception类型、可选型参1:JoinPoint类型)
                属性:value                 表示切入点表达式,来确定切面执行的位置
                           throwing            自定义变量,表示目标方法抛出的异常,变量名必须和切面方法的形参Exception的名相同
@After:最终通知                                                                                                   //了解即可     目标方法执行之前执行。无论目标方法是否抛出异常,该增强均会被执行。
                                (方法:public、void、可选型参1:JoinPoint类型)
                属性:value                 表示切入点表达式,来确定切面执行的位置



Pointcut位置:使用Aspectj切入点表达式          execution(访问修饰符   返回值类型   包名类名方法名(参数类型))   异常类型)                                          //红色表示该区域可以省略
                                                                        *:0或多个任意字符
                                                                        ..:1)参数中表任意个数、类型   2)包名后表当前包及子包路径
                                                                        +:1)类名后表当前类及子类      2)接口后表当前接口及实现类                                                                                                                                                        
                        //切入点表达式可以表示方法定义说明


使用:

  1. 创建业务接口,实现目标类
  2. 创建切面类(普通的类),创建切面(方法)
    1. 在切面类上加注解@Aspectj             //切面类注解:表示切面功能的类
    2. 在切面类的方法上加入Aspectj框架的通知注解      //  所有的切面方法都一个可选的型参1:JoinPoint类型
                                                                                     //该类型的对象本身就是切入点表达式。通过该参数,可获取切入点表达式、方法签名、目标对象等。
                                                                                                                               //如:   对象.getArgs()返回通知方法参数列表     对象.getSignature()返回连接点签名
  3. 在spring配置文件中:
    1. 声明目标类对象            <bean>
    2. 声明切面类对象            <bean>
    3. 声明自动代理生成器     <aop:aspectj-autoproxy />         //调用Aspectj框架的功能寻找容器中的所有对象,把每个目标对象加入切面类中的功能,生成代理
                                                                                              //每个代理对象是---修改了 的内存中的目标对象,这个目标对象就是代理对象
  4. 创建测试类,测试目标方法执行时参加的切面功能

 @Pointcut                辅助的注解,用来定义和管理切入点(多个切入点表达式重复,可以复用)
                                位置:自定义方法上面,这个方法可以看作是切入点表达式的别名,在其他的通知注解中可以使用该方法名---就表示这个切入点表达式
                                   (一般在切面类自定义一个私有方法方法)
                属性:value                 表示切入点表达式,来确定切面执行的位置,此时该注解的方法的方法名就是该value值---切入点表达式

                        @Pointcut(value = "切入点表达式")

        在通知注解中使用:@Before(Value = "方法名()")
        


Spring集成MyBatis

spring能集成很多框架,能让开发人员使用其他框架更方便
集成使用的是:spring IoC技术

使用mybatis需要创建mybatis中的对象-----Dao接口的代理对象
                1)需要用到:SqlSession对象.getMapper(dao接口.class)得到dao对象
                                  需要SqlSessionFactory,创建SqlSessionFactory对象,才能openSession()得到SqlSession对象
                2)需要DataSource对象,功能更强大的的连接池对象代替mybatis自己的PooledDataSource


集成的步骤:
        1)创建maven项目,加入依赖:spring依赖、mybatis依赖、MySQL驱动、junit单元测试、阿里的druid连接池
                                                            mybatis-spring依赖:mybatis官网提供,用来在spring项目中,创建mybatis对象
                                                            spring有关事务的依赖

                     mybatis与spring整合时,事务是自动提交的
        mybatis:
                2)创建实体类                  //与表的列名对应
                3)创建Dao接口和mapper文件写sql语句
                4)写mybatis主配置文件
                        

mybatis主配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

  <!--设置日志功能-->
  <settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>     
  </settings>

  <!--声明别名-->
  <typeAliases>
    <package name="包名" >
  </typeAliases>

  <!--指定其他mapper文件的位置:为了找到其他文件中的sql语句-->
  <mappers>
    <package name="mapper文件所在的包名" />  
  </mappers>
</configuration>


        5)创建service接口和他的实现类,类方法就是操作dao         //mvc    别忘了实现类的私有属性是dao接口哦
        6)创建spring配置文件
                1.声明数据源DataSource,使用阿里的Druid连接池                    //  DruidDataSource配置 · alibaba/druid Wiki · GitHub 参考配置
                        配置url、username、password这三项    //Druid会自动跟url识别驱动类名,所以不需要配置属性driverClassName

                2.声明SqlSessionFactoryBean类(mybatis提供的),在类内部创建SqlSessionFactory对象       //mybatis-spring依赖提供了SqlSessionFactoryBean类
                3.声明MapperScannerConfiguration类,在类内部创建dao代理对象        //创建好的对象都放到spring容器中
                4.声明Service对象,把 3.的dao赋值给service对象的属性     //mvc

        

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"          
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--声明数据源DataSource      -->        
    <!--init是初始方法,会在构造方法执行完毕后自动调用,在DruidDataSource类中存在  close是销毁方法,在容器销毁时会调用该方法,用来把内存中的连接对象删除掉
    这俩方法都是在DruidDataSource类中定义好的方法名-->       
    <bean id=" " class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
        <property name="url" value="jdbc:mysql://localhost:3306/数据库" />
       <property name="username" value="用户" />
       <property name="password" value="密码" />
       
    </bean> 
    <!--声明数据源方式二:灵活方式、加载外部属性配置文件--使用变量-->   
    <context:property-placeholder location="classpath:xxx.properties"> 
    <bean id=" " class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
       <property name="url" value="${jdbc的key值}"/>
       <property name="username" value="${用户名的key值}" />
       <property name="password" value="${密码的key值}" />
    </bean>



    <!--声明SqlSessionFactoryBean,在这个类内部创建SqlSessionFactory-->
    <bean id=" " class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--指定数据源头数据源 -->
        <property name="dataSource" ref="数据源对象id" />
        <!--指定mybatis主配置文件//因为用来mybatis数据源是是主配置里写的,集成框架改在spring配置文件了,要关联一下
        Resource可以直接使用value属性赋值-->
        <!--主配置文件路径   classpath:xxx.xml     类路径下的.xml-->
        <property name="configLocation" value="主配置文路径" />      
    </bean>

    <!--声明MapperScannerConfiguration-->
    <!--MapperScannerConfiguration作用是循环basePackage所表示的包名,把包中的每个接口都找到,
    调用SqlSession对象.getMapper(dao接口.class)创建出代理对象,把代理对象放到容器里(代理dao对象在容器的名是接口名的小驼峰)-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfiguration"> 
        <!--指定SqlSessionFactory对象的名称 -->
       <property name="SqlSessionFactoryBeanName" value="上面SqlSessionFactoryBean的id值" />
        <!--创建dao代理对象    要参加对象就得有SqlSession对象.getMapper(dao接口.class)中的dao接口.class,所以要指定dao接口所在的包名-->
        <property name="basePackage" value="dao接口的包名" />
    </bean>        
    
    <!--声明service-->
    <bean id=" " class="service实现类全名"> 
       <property name="类的属性名(dao接口作为的service对象属性)" ref="创建dao代理对象(即接口的小驼峰)" />
       
   </bean>
    
</beans>


        7)测试dao访问数据库

       


   

spring事务的依赖
<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>5.2.5.RELEASE</version>
</dependency>
<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.2.5.RELEASE</version>
</dependency>

  mybatis-spring集成依赖
<dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.3.1</version>
</dependency>

德鲁伊连接池
<dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.12</version>
</dependency>

插件:
<build>
        <resources>
                <resource>
                        <directory>src/main/java</directory><!--所在的目录-->
                        <includes><!--包括目录下的.properties,.xml文件都会扫描到-->
                                <include>**/*.properties</include>
                                <include>**/*.xml</include>
                        </includes>
                        <filtering>false</filtering>
                </resource>
        </resources>
</build>


事务

事务放在service类的业务方法(public)之上
因为不同技术做事务是不同的:jdbc、mybatis           -------语句都不一样,所需需要有一个统一的方法:spring统一管理事务,把不同的数据库访问技术统一起来

spring事务管理器:是一个接口        PlatformTransactionManager
                                方法:
                                        commit()                          提交事务
                                        rollback()                         归滚事务
                                        getTransaction()                   获取事务状态
                                               
                                实现类:该接口有很多实现类,一个实现类代表一种数据库访问技术,有实现类完成事务的提交、回滚
                                               实现类创建出的事务管理器器对象:管理不同的数据库访问技术的事务处理    //由spring做提交、回滚
                                        实现类:
                                        DataSourceTransactionManager                        //使用 JDBC 或 My Batis 进行 数据库操作 时使用。
                                        HibernateTransactionManager                          //使用 Hibernate 进行持久化数据时使用。

              

        事务的提交、回滚的时机:业务方法抛出运行时异常,事务回滚。其他清空事务提交

         
        事务使用的AOP的环绕通知:spring在目标方法前和后都增强功能,不需要修改代码      //在业务方法上增加切面功能
                                        @Around(所有的业务方法)
                                        public xxx 切面方法(传入业务方法){
                                                try{
                                                        使用spring业务管理器开启事务  //    PlatformTransactionManager对象.beginTransaction()               
                                                        执行目标方法                              //业务方法
                                                        业务正常执行,提交事务           //PlatformTransactionManager对象.commit()       
                                                }catch(Exception){
                                                        若出异常,回滚事务                  //PlatformTransactionManager对象.rollback()  
                                                }             
                                        }

        怎样让spring知道哪些业务方法有事务?                        
        TransactionDefinition接口:定义了事务描述相关的三类常量:
                事务隔离级别:
定义了五个事务隔离级别常量
                        ISOLATION_DEFAULT:采用 DB 默认的事务隔离级别。 MySql 的默认为 RE PEAT ABLE_READ、 Oracle默认为 READ_COMMITTED 。
                        ISOLATION_READ_UNCOMMITTED:读未提交。未解决任何并发问题。
                        ISOLATION_READ_COMMITTED:读已提交。解决脏读,存在不可重复读与幻读。
                        ISOLATION_REPEATABLE_READ:可重复读。解决脏读、不可重复读,存在幻读
                        ISOLATION_SERIALIZABLE:串行化。不存在并发问题。
                事务传播行为:    业务方法在调用时,事务在方法之间的传递和使用             //可以标识方法有没有事务
                        PROPAGATION_REQUIRED:默认的播行为。必须在事务内执行。若当前环境存在事务,就加入到当前事务中;若当前没有事务,则创建一个新事务,在新事务中执行
                                                                
                        PROPAGATION_REQUIRES_NEW:方法需要一个新事务。调用方法,方法当前环境存在一个新事务,则当前环境的事务暂停,知道新事物执行完毕。
                                                                                                                                           方法当前环境若不存在事务,则新建一个事务,在新事物中执行      
                                                                
                        PROPAGATION_SUPPORTS:当前环境有事务就支持事务,当前环境没事务也可以正常执行
                                                                
                        不用掌握:
                        PROPAGATION_MANDATORY
                        PROPAGATION_NESTED
                        PROPAGATION_NEVER
                        PROPAGATION_NOT_SUPPORTED
                事务默认超时时限:   一个业务方法最长的执行时间,到达时间没有执行完毕,spring会回滚事务                           //以秒为单位。默认-1,没有超时时间
                        TIMEOUT_DEFAULT
        

 方式一:使用 Spring 的事务注解管理事务------通过spring自己的注解@Transactional 注解方式, 可将事务注入到相应 public 方法中,实现事务管理。
                特点:适合中小型项目:因为注解在要在源代码写,但使用方便
                           spring自己提供的事务控制
                
        @Transactional        位置:1)放在业务方法(publice)之上           2)类上 (相当于所有public方法都加)                             //控制(隔离级别、传播行为、超时)
                 @Transactional(属性=属性值,属性=属性值,属性=属性值,……)                //使用设置的值
                 @Transactional                                        //使用的时默认值
                属性:propagation                         事务传播属性。该属性值为:Propagation 类的枚举值        //默认值为Propagation.REQUIRED
                           isolation                               事务的隔离级别。该属性为 Isolation 类的枚举值                //默认值为Isolation.DEFAULT
                           readOnly                              该属性为 布尔值。用于设置该方法对数据库的操作是否是只读的。        //默认值为 false 不是只读     //只读:只查不改
                           timeout                                超时时限。单位为秒,类型为 int                                         //默认值为-1 ,即没有时限。
                           回滚:先查看是异常是否在列表中,如果在一定回滚。如果抛出的异常不再列表,会检查异常是否为运行时异常,若是则回滚
                           rollbackFor                          回滚的异常类列表--->类型为 Class[]             //类类型                                     //默认值为空数组         //只有一个异常类时,可以不使用数组
                                                                       表示当方法抛出设置在列表里的异常类时,要进行回滚                   
                           rollbackForClassName        回滚的异常类列表---->String[]    //字符串类型,指定需要回滚的异常类类名   //默认值为空数组      //只有一个异常类时,可以不使用数组 
                           不回滚:
                           noRollbackFor                     指定不需要回滚的异常类列表 --->类型为 Class[]                                             //默认值为空数组       //只有一个异常类时,可以不使用数组
                           noRollbackForClassName   指定不需要回滚的异常类类名--->类型为 String[]                                             //默认值为空数组       //只有一个异常类时,可以不使用数组

     

        使用步骤:1)在spring的配置文件,声明事务的内容:声明事务管理器--->说明使用哪个事务管理器对象
                                                                                             声明使用注解管理事务:开启注解驱动
                                

<?xml version="1.0" encoding="UTF-8"?>
<beans>  
    <!--声明数据源-->
    <bean id=" " class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
        <property name="url" value="jdbc:mysql://localhost:3306/数据库" />
        <property name="username" value="用户" />
        <property name="password" value="密码" />
    </bean> 

    <!--声明SqlSessionFactoryBean,在这个类内部创建SqlSessionFactory-->
    <bean id=" " class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="数据源对象id" />
        <property name="configLocation" value="主配置文路径" />      
    </bean>

    <!--声明MapperScannerConfiguration-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfiguration"> 
        <property name="SqlSessionFactoryBeanName" value="上面SqlSessionFactoryBean的id值" />
        <property name="basePackage" value="dao接口的包名" />
    </bean>        
    
    <!--声明service-->
    <bean id=" " class="service实现类全名"> 
        <property name="类的属性名(dao接口作为的service对象属性)" ref="创建dao代理对象(即接口的小驼峰)" />
    </bean>

    <!--声明事务的控制:-->
    <!--1.声明事务管理器     起一个语义化id名,一般为transactionManager-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
        <!--指定数据源DataSource-->
        <property name="dataSource" ref="数据源对象id" />
    </bean>
    <!--可以有多个事务管理器,因为可以有多个数据源-->
    <bean id="transactionManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
        <property name="dataSource" ref="数据源对象id" />
    </bean>


    <!--2.开启事务注解驱动:告诉框架使用注解管理事务       会加入spring-tx.xsd文件-->
    <!--事务管理驱动也可以指定不同的事务管理器-->
    <tx:annotation-driven transaction-manager="事务管理器id"/>


</beans>


                          2)正在类的源代码中加入 @Transactional


方式二:使用 AspectJ 的 AOP 配置文件中来声明事务控制---声明式事务
        特点:不用该源代码,代码和事务是分开的,适合大项目
                    不容易理,解配置复杂
        
        使用步骤:1)在pom.xml加入AspectJ 依赖
                                        <dependency>
                                                <groupId>org.springframework</groupId>
                                                <artifactId>spring-aspects</artifactId>
                                                <version>5.2.5.RELEASE</version>
                                        </dependency>
                          2)在spring配置文件声明事物的内容
                                1.声明业务管理器
                                2.声明业务方法需要的事务属性
                                3.声明切入点表达式
                        

<?xml version="1.0" encoding="UTF-8"?>
<beans>  
    <!--声明数据源-->
    <bean id=" " class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> 
        <property name="url" value="jdbc:mysql://localhost:3306/数据库" />
        <property name="username" value="用户" />
        <property name="password" value="密码" />
    </bean> 

    <!--声明SqlSessionFactoryBean,在这个类内部创建SqlSessionFactory-->
    <bean id=" " class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="数据源对象id" />
        <property name="configLocation" value="主配置文路径" />      
    </bean>

    <!--声明MapperScannerConfiguration-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfiguration"> 
        <property name="SqlSessionFactoryBeanName" value="上面SqlSessionFactoryBean的id值" />
        <property name="basePackage" value="dao接口的包名" />
    </bean>        
    
    <!--声明service-->
    <bean id=" " class="service实现类全名"> 
        <property name="类的属性名(dao接口作为的service对象属性)" ref="创建dao代理对象(即接口的小驼峰)" />
    </bean>

    <!--声明式事务:-->
    <!--1.声明事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
        <!--指定数据源DataSource-->
        <property name="dataSource" ref="数据源对象id" />
    </bean>

    <!--2.:配置事务通知:声明业务方法的事务属性(隔离级别、传播行为、超时)-->
    <!--id:给业务方法配置事务段代码起名    transaction-manager:事务管理器id-->
    <tx:advice id="" transaction-manager="transactionManager">
        <!--给具体的业务方法增加事务说明-->
        <!--属性-->
		<tx:attributes>
            <!--name:1)业务方法名   2)带有通配符的业务方法名成     3)*
                propagation:传播行为、isolation:隔离级别、read-only:只读、timeout:超时、rollback-for:回滚异常类列表(使用全限定名称,多个用逗号隔离)、no-rollback-for:不回滚异常类列表    
            -->
			<tx:method name="业务方法名" propagation="传播行为" isolation="隔离级别" read-only="是否只读" timeout="时间" rollback-for="回滚异常类列表"/>
			<tx:method name="一部分方法名结合*通配符" />
			<tx:method name="*" />
            ……
		</tx:attributes>
	</tx:advice>

    <!-- 3.声明切点表达式:表示哪些包中的那些类,类中的方法参与事务 -->
    <aop:config>
        <!--声明切点表达式    expression:切入点表达式,表示哪些包中的类中的方法参与事务-->
		<aop:pointcut expression="切入点表达式" id="自己起切入点表达式的名称" />
        <!--关联切人点表达式和事务通知-->
		<aop:advisor advice-ref="事务通知id" pointcut-ref="切人点表达式id" />
	</aop:config>

    


</beans>


        


WEB项目

1)maven创建web项目:maven archetype webapp
2)加入 servlet 、jsp 、spring、mybatis等依赖            //别忘了web项目是war,普通Java项目是jar

                <!-- servlet依赖 -->
                <dependency>
                        <groupId>javax.servlet</groupId>
                        <artifactId>javax.servlet-api</artifactId>
                        <version>3.1.0</version>
                        <scope>provided</scope>
                </dependency>
                <!-- jsp依赖 -->
                <dependency>
                        <groupId>javax.servlet.jsp</groupId>
                        <artifactId>jsp-api</artifactId>
                        <version>2.2.1-b03</version>
                        <scope>provided</scope>
                </dependency>
3)创建实体类对应数据库表、Service 层、 Dao 层、
4)配置各种文件:applicationContext.xml 、jdbc.properties、mybatis.xml、pom.xml
5)创建servlet接受请求的参数,创建容器,调用Service层的Service对象
                缺点:每次请求调用servlet都创建容器对象,浪费了 -----解决:该容器应该项目共享     使用监听器:
                                        1.使用 ServletContextListener(初始时执行的方法,销毁时执行的方法)
                                        2.创建好的容器放到ServletContext应用域中
                ContextLoaderListener是一个监听器对象,是spring框架提供的,
                作用:可以创建容器对象1次,把容器对象放入ServletContext应用域中
                使用步骤:1.在pom.xml中加入依赖spring-web  //该依赖包含了ContextLoaderListener类
                                                <dependency>
                                                        <groupId>org.springframework</groupId>
                                                        <artifactId>spring-web</artifactId>
                                                        <version>5.2.5.RELEASE</version>
                                                </dependency>
                                  2.在web.xml声明监听器存在
                                  3.从ServletContext中获取容器对象:String key = WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE;
                                                                                             ServletContext sc = request对象.getServletContext     //HttpServletRequest对象的方法     //获取ServletContext应用域
                                                                                                                       或:getServletContext()
                                                                                             sc.getAttribute(key);        //获取容器对象
                                  3.spring框架提供了一个方法可以简单地获取容器对象:WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext())
                                                                                                                或:   WebApplicationContextUtils.getWebApplicationContext(getServletContext())

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
                      https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
  version="5.0"
  metadata-complete="true">

	<servlet>
		<servlet-name>fdsafdsagfdsafdsa</servlet-name>
		<servlet-class>com.bjpowernode.servlet.HelloServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>fdsafdsagfdsafdsa</servlet-name>
		<url-pattern>/资源/fd/saf/d/sa/fd/sa/fd</url-pattern>   
	</servlet-mapping>
	



    <!--自定义容器使用的配置文件路径    context-param:上下文参数,给监听器提供参数的-->
    <context-param>
        <!--固定的参数名    contextConfigLocation表示自定义的spring配置文件的路径-->
        <param-name>contextConfigLocation</param-name>
        <!--自定义配置文件的路径    类路径下的xxx.xml文件-->
        <param-value>classpath:xxxx.xml,第二个配置文件路径,第三个,……</param-value>
    </context-param>

    <!--声明监听器
        默认监听器:创建容器对象时,读取配置文件:/WEB-INF/applicationContext.xml
        路径和文件名可以自定义,不适应默认规则-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
  

   
</web-app>

        ContextLoaderListener类:
                             
                                
                                               initWebApplicationContext(): 
                                                        创建容器对象               // WebApplicationContext时web项目中使用的容器,它继承ApplicationContext
                                                                                                      public interface WebApplicationContext extend ApplicationContext
                                                        
                                                        把容器对象放入ServletContext               
                                                        
                        
6)创建jsp提交请求参数、作为视图显示请求的处理结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值