万字详解Spring框架

简介: 学习SpringIOC,AOP两大特性以及衍生的相关知识点, 千万不要错过!!!

一、简介

Spring简介

Spring是为了 解决企业应用开发的复杂性 而创建的一个开源框架;是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
IoC : Inversion of Control 控制反转
AOP : Aspect Oriented Programming 依赖注入

常用jar包

1.spring-core.jar
core是spring框架基本的核心工具类。spring其他组件都要使用到这个jar的类。是其他组件的基本核心。外部依赖Commons Logging, (Log4J)。

2.spring-beans.jar
beans是基本的jar。他包含访问配置文件,创建和管理bean,以及控制反转,注入操作的所有相关类。如果只用到Ioc/DI,则只需引入core与beans就足够了。平常用的Autowired就是用的这个包的

3.spring-aop.jar
这个jar 文件包含在应用中使用Spring 的AOP 特性时所需的类和源码级元数据支持。使用基于AOP 的Spring特性,如声明型事务管理(Declarative Transaction Management),也要在应用里包含这个jar包。

4.spring-context.jar
这个 jar 文件为 Spring 核心提供了大量扩展。可以找到使用 Spring ApplicationContext 特性时所需的全部类, JDNI 所需的全部类, UI 方面的用来与模板 (Templating) 引擎如 Velocity、 FreeMarker、JasperReports 集成的类,以及校验 Validation 方面的相关类。

5.spring-webmvc.jar
这个 jar 文件包含 Spring MVC 框架相关的所有类。包含国际化、标签、Theme、视图展现的 FreeMarker、JasperReports、Tiles、Velocity、XSLT 相关类。当然,如果你的应用使用了 独立的 MVC 框架,则无需这个 JAR 文件里的任何类。

6.spring-jdbc.jar
这个jar 文件包含对Spring 对JDBC 数据访问进行封装的所有类。

7.spring-web.jar
这个jar 文件包含Web 应用开发时,用到Spring 框架时所需的核心类,包括自动载入Web Application Context 特性的类、Struts 与JSF 集成类、文件上传的支持类、Filter 类和大量工具辅助类。平时用到RequestMapping就是来自这个包的.

其他jar包
在这里插入图片描述

二、Spring-IOC(控制反转)

IOC简介

控制反转(IoC,Inversion of Control),是一个概念,是一种思想。 控制反转就是对对象控制权的转移,从程序代码本身反转到了外部容器。把对象的创建、初始化、 销毁等工作交给spring容器来做。由spring容器控制对象的生命周期。

Spring-IOC程序搭建步骤

1、导入jar包
2、创建spring配置文件(src目录下)
3、Bean的定义与注册
4、从spring容器中获取Bean

相关jar包
在这里插入图片描述

注:

 <!-- bean的定义:以下配置相当于创建一个类的对象。即:
 SomeServiceImpl someServiceImpl= new SomeServiceImpl(); -->
  <bean id="someServiceImpl" class="com.bjsxt.service.impl.SomeServiceImpl"></bean>

解决Spring配置文件没有提示

如果在没有网络的情况下,spring中基于联网的 .xsd配置文件的约束文件会无法使用,这样就需要我们其提前下载并手动添加到本地,步骤如下:
  • 找到XML Catalog,添加下载好的约束文件

在这里插入图片描述

  • 注意如下选项并保存

在这里插入图片描述

BeanFactory和ApplicationContext

关系

ApplicationContext 是 Spring 应用程序中的中央接口,用于向应用程序提供配置信息 它继承了 BeanFactory 接口,所以 ApplicationContext 包含 BeanFactory 的所有功能以及更多功能!它的主要功能是支持大型的业务应用的创建特性。

区别

BeanFactory当调用getBean获取相应对象时,才创建对象
ApplicationContext容器初始化时,所有的容器中的bean创建完毕

Bean的创建

在applicationContext.xml的< beans>标签中创建< bean>标签, 一个< bean>标签表示一个java对象 ,该对象由Spring容器创建和管理,

Bean标签的属性

标签 属性
id 唯一标示该bean
name 和id相同的作用
class 该类的权限定名,指向对于的类
autowire 表示bean的自动装配

Bean的装配方式

Bean的装配,即Bean对象的创建
Bean的装配方式有三种
第一种:spring从两个角度实现自动化装配:组件扫描和自动装配。
第二种:通过java代码装配bean
第三种:在XML中装配bean

动态装配方式

1、创建Bean对象
2、注册工厂,创建工厂对象
3、从工厂中获取someServiceImpl的bean对象


public class ServiceFactory {
    
    //动态工厂方式,创建bean对象
    public SomeService getSomeFactory(){
        SomeService someServiceImpl=new SomeServiceImpl();
        
        return someServiceImpl;
    }
    
}
<!-- 注册工厂 -->
    <bean id="serviceFactory" class="com.bjsxt.factory.ServiceFactory"></bean>
    <!-- 从工厂中获取someServiceImpl的bean对象 -->
    <bean id="someServiceImpl" factory-bean="serviceFactory" factory-method="getSomeFactory"></bean>

public class SomeTest {
    
    //该方式的优点:实现了测试类与service实现类的解耦合
    @Test
    public void someTest01(){
        //创建容器对象,ApplicationContext容器初始化时,所有的容器中的bean创建完毕
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        SomeService service = ac.getBean("someServiceImpl", SomeService.class);
        service.doSome();
    }
    
}

静态装配方式

1、创建bean对象
2、从工厂中获取someServiceImpl的bean对象
<!-- 静态工厂配置,类名对象,类名,方法 -->
    <bean id="someServiceImpl" class="com.bjsxt.factory.ServiceFactory" factory-method="getSomeFactory"></bean>

Bean的作用域

作用域名 作用
singleton 默认使用, 在整个Spring IoC 容器中,使用 singleton 定义的Bean将只有一个实例
prototype 原型模式,每次通过容器的getBean 方法获取prototype定义的Bean 时,都将产生一个新的Bean实例
request 对于每次HTTP请求,使用request定义的Bean都将产生一个新的实例,每次HTTP请求都将产生不同的Bean实例,该作用域仅在给予web的Spring ApplicationContext情形下有效
Session 对于每次HTTP Session ,使用session定义的Bean都将产生一个新实例,该作用域仅在给予web的Spring ApplicationContext情形下有效
global session 每个全局得HTTP Session对应一个Bean实例,该作用域仅在给予web的Spring ApplicationContext情形下有效

三、DI依赖注入

依赖注入(Dependency Injection):这就是DI,字面上理解,依赖注入就是将服务注入到使用它的地方。对象只提供普通的方法让容器去决定依赖关系,相对于IoC而言,依赖注入(DI)更加准确地描述了IoC的设计理念。

所谓依赖注入,即组件之间的依赖关系由容器在应用系统运行期来决定,也就是由容器动态地将某种依赖关系的目标对象实例注入到应用系统中的各个关联的组件之中。

环境

演示所用的两个实体类

在这里插入图片描述
在这里插入图片描述

测试类的测试方法

    @Test
    public void someTest01(){
        //创建容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Star star =ac.getBean("star", Star.class);//getBean(id, class)
        System.out.println(star);
    }

简单类型注入

简单类型数据注入包括普通数据注入、引用数据类型注入
<bean id="star" class="com.bjsxt.pojo.Star" >
        <!-- 简单数据类型  -->
        <property name="name" value="旭旭宝宝"></property>
        <property name="age"  value="39" ></property>
        <!-- 引用数据类型注入参考的是下面的id -->
        <property name="partener"  ref="partener" ></property>
    </bean>
    <bean id="partener" class="com.bjsxt.pojo.Partener" >
        <property name="name" value="韩茜茜"></property>
    </bean>

集合类型注入

每种集合类型使用的标签
在这里插入图片描述
简单案例

<bean id="someService" class="com.bjsxt.pojo.SomeService" >
        <property name="myArray">
            <array>
                <value>北京</value>
                <value>上海</value>
            </array>
        </property>
        <property name="myList">
            <list>
                <value>男</value>
                <value>女</value>
            </list>
        </property>
        <property name="mySet">
            <set>
                <ref bean="partener1" />
                <ref bean="partener2" />
            </set>
        </property>
        <property name="myMap">
            <map>
                <entry key="qq" value="1315690999"></entry>
                <entry key="moblie" value="18326989999"></entry>
            </map>
        </property>
        <property name="myProps">
            <props >
                <prop key="兴趣">看动漫</prop>
                <prop key="爱好">敲代码</prop>
            </props>
        </property>
    </bean>

域属性自动注入

域属性自动注入的方式
全局自动注入(根标签下) :default-autowire
局部自动注入(注册bean时使用): autowire="byType"

自动注入的类别

byName 方式域属性自动注入,根据属性名自动装配。此选项将检查容器并根据名字查找与属性完全一致的bean,并将其与属性自动装配
byType 如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配;如果存在多个该类型bean,那么抛出异常,并指出不能使用byType方式进行自动装配

空值注入

空字符串注入:通过value标签        <property name="name" ><value/></property>
空值注入:通过null标签            <property name="name" ><null/></property>

构造注入

    1、通过name属性的构造
    <constructor-arg name="name" value="郭靖"></constructor-arg>
    
    2、通过index属性的构造,但value的类型顺序必须与构造器中的类型一致
    <constructor-arg index="0" value="郭靖"></constructor-arg>
    
    3、自动构造,但value的类型顺序必须与构造器中的类型一致
    <constructor-arg  value="郭靖"></constructor-arg>

DI之注解

在使注解注入用前需要扫描使用注解的包

<context:component-scan base-package="com.bjsxt.pojo"></context:component-scan>

常用注解


@Service 该注解添加在 Service的实现类中

@Controller 该注解添加在 Controller类的前面,表明当前controller交给spring管理

@Autowired 引用数据类型注入,默认byType。常用于controller与service的实现类中

@Qualifier(“id”) 与@Autowired 联合使用 byName 方式注入

@Value 简单数据类型注入。常用于自定义配置文件中的值的引用。

@Resource 引用数据类型默认使用 byName 方式,若找不到名称匹配的bean ,才会采用 byType 方式

@Scope() 表明采取什么作用域。单态模式singleton:默认使用原型模式prototype:每次调用都会传建一个新的bean

四、Spring-AOP(面向切面)

介绍

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

代理模式

代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。
抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
二十三种设计模式之一 ,详情见本连接第三部分

作用

可以隐藏目标类的具体实现
在不修改目标类代码的情况下能够对其功能进行增强。

分类

静态代理

测试静态代理,写一个接口,一个目标实现类,再写一个代理类也实现该接口,并将目标类对象传入代理类中,代理类调用目标类对象的方法。最后测试。
注意: 代理类与目标类实现相同的接口
public class SomeTest {
    public static void main(String[] args) {
        //定义目标对象
        SomeService target = new SomeServiceImpl();
        //定义目标对象的代理对象
        SomeService proxy = new ServiceProxy(target);
        String result = proxy.doSome();
        System.out.println(result);
    }
}

jdk动态代理

动态代理不在程序中声明代理类代码,而是在运行中使用 Proxy 类 动态执行代理类的方法。
应用场景:目标类
public class SomeTest {
    public static void main(String[] args) {
        //定义目标对象
        final SomeService target = new SomeServiceImpl();
        //定义目标对象的代理对象
        SomeService proxy = (SomeService) Proxy.newProxyInstance(target.getClass().getClassLoader(),//目标类的类加载器
            target.getClass().getInterfaces(),//目标类实现的所有接口
            new InvocationHandler() {//调用处理器
                //proxy:代理对象
                //method:目标方法
                //args:目标方法参数
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    String result = (String) method.invoke(target, args);
                    return result.toUpperCase();
                }
            });
        String result1 = proxy.doSome();
        System.out.println(result1);
    }
}

cglib动态代理

应用场景: 实现目标类没有实现目标接口
注意: CGLIB 代理需要引入 cglib 架包
public class SomeTest {
    public static void main(String[] args) {
        //定义目标对象
        SomeServiceImpl target = new SomeServiceImpl();
        //定义目标对象的代理对象
        SomeServiceImpl proxy = new CglibProxyFactory(target).proxyCreator();
        String result1 = proxy.doSome();
        System.out.println(result1);
    }
}

基于Schema-based方式的通知声明

搭建编程环境

  1. 导入jar包(SpringIOC包+AOP包)
  2. 在src下创建applicationcontext.xml配置文件
  3. 编写通知类.相关的接口 ,实现类以及方法
  4. 由Spring容器对象获取切点所在bean对象调用切点方法完成功能操作。(注册通知类 注册切面 指定目标对象 指定目标接口 指定切面)
  5. 运行测试

接口类

public interface SomeService {
    void doSome();
    String doOther();
}

实现类

public class SomeServiceImpl implements SomeService {
    
    
    public SomeServiceImpl() {
        System.out.println("无参构造器执行!");
    }

    @Override
    public void doSome() {
        System.out.println("doSome()方法执行!");
    }

    @Override
    public String doOther() {
        System.out.println("doOther()方法执行!");
        return "return doOther";
    }

}

测试方法类


public class SomeTest {
    
    
    //该方式的优点:实现了测试类与service实现类的解耦合
    @Test
    public void someTest01(){
        //创建容器对象,ApplicationContext容器初始化时,所有的容器中的bean创建完毕
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        SomeService service = ac.getBean("proxyFactoryBean", SomeService.class);
        service.doSome();
        String result = service.doOther();
        System.out.println(result);
        
    
    }
    

}

配置文件

<?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">

<!-- 注册通知类 -->
    <bean id="someServiceImpl" class="com.bjsxt.service.impl.SomeServiceImpl"></bean>
<!-- 注册切面,前置通知 -->
<bean id="myMethodBeforeAdvice" class="com.bjsxt.aspects.MyMethodBeforeAdvice"></bean>
<!-- 注册切面,后置通知 -->
<bean id="afterReturning" class="com.bjsxt.aspects.AfterReturning"></bean>
<!-- 注册切面,环绕通知 -->
<bean id="myMethodInterceptor" class="com.bjsxt.aspects.MyMethodInterceptor"></bean>
<!-- 注册切面,异常通知 -->
<bean id="myThrowsAdvice" class="com.bjsxt.aspects.MyThrowsAdvice"></bean>
<!-- 注册代理 -->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
    <!-- 指定目标对象 -->
    <property name="target" ref="someServiceImpl"></property>
    <!-- 指定目标类实现所有接口,接口,接口所在类 -->
    <property name="interfaces" value="com.bjsxt.service.SomeService"></property>
    <!-- 指定切面 -->
    <!-- <property name="interceptorNames" value="myMethodBeforeAdvice"></property> -->
    <!-- <property name="interceptorNames" value="afterReturning"></property> -->
     <property name="interceptorNames" value="myMethodInterceptor"></property> 
    <!-- <property name="interceptorNames" value="myThrowsAdvice"></property> -->
</bean>

</beans>

前置通知

/**
     * 前置通知
     * method:目标方法
     * args:目标方法参数列表
     * target:目标对象
     */
public class MyMethodBeforeAdvice  implements MethodBeforeAdvice{
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("MyMethodBeforeAdvice.before(前置通知执行)");
        
    }

    

}

后置通知

/**
 * 后置通知
 * returnValue:目标方法的返回值
 *
 */
public class AfterReturning  implements AfterReturningAdvice{
    
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("AfterReturning.afterReturning(后置通知方法的执行)"+returnValue);
        
        if (returnValue!=null) {
            System.out.println("AfterReturning.afterReturning()"+((String)returnValue).toUpperCase());
        }
    }

}

环绕通知

/**
 * 切面:环绕通知
 * invocation:方法调用器
 *
 */
public class MyMethodInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation ) throws Throwable {
        
        System.out.println("环绕通知:目标方法执行之前");
        //调用执行目标方法
        Object result = invocation.proceed();
        if (result!=null) {
            result=((String)result).toUpperCase();
        }
        System.out.println("环绕通知:目标方法执行之后");
        return result;
    }

}

异常通知

/**
 * 切面:异常通知
 * 需要自己创建
 *
 */
public class MyThrowsAdvice implements ThrowsAdvice {
    public void afterThrowing(Exception ex) {
        System.out.println("异常通知执行!!!");
    }
}

基于AspectJ方式之注解的方式通知声明

搭建编程环境

  1. 创建目标类(接口以及实现类测试类)
  2. 定义通知类,在前置通知方法上添加相应的注解,表示是什么通知
  3. 创建配置文件(注册目标类,注册切面,注册自动代理)
  4. 运行测试类

接口类

public interface SomeService {
    void doSome();
    String doOther();
}

实现类

public class SomeServiceImpl implements SomeService {
    
    
    public SomeServiceImpl() {
        System.out.println("无参构造器执行!");
    }

    @Override
    public void doSome() {
        System.out.println("doSome()方法执行!"+1/0);
        //System.out.println("doSome()方法执行!");
    }

    @Override
    public String doOther() {
        System.out.println("doOther()方法执行!");
        return "love";
    }

}

测试类

public class SomeTest {
    
    @Test
    public void someTest01(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        SomeService service = ac.getBean("someServiceImpl", SomeService.class);
        service.doSome();
        String result = service.doOther();
        System.out.println(result);
    }
}

配置文件

<?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
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 注册目标类 -->
    <bean id="someServiceImpl" class="com.bjsxt.service.impl.SomeServiceImpl"></bean>
    <!-- 注册切面 -->
    <bean id="myAspect" class="com.bjsxt.aspects.MyAspect"></bean>
    <!-- 注册自动代理 -->
    <aop:aspectj-autoproxy/>
    
</beans>

前置通知

@Before("execution(* *..service.*.doSome(..))")
    public void before(){
        System.out.println("前置通知方法执行!");
    }

后置通知

@AfterReturning(value="execution(* *..service.*.doOther(..))",returning="result")
    public void afterReturning(Object result){
        System.out.println("后置通知方法执行! 目标方法的返回值是"+result);
    }

环绕通知

@Around("execution(* *..service.*.doOther(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("环绕通知:目标方法执行之前!");
        String result = (String) pjp.proceed();
        if(result!=null){
            result = result.toUpperCase();
            
        }

异常通知

@AfterThrowing(valujavae="execution(* *..service.*.doSome(..))",throwing="ex")
    public void throwing(Exception ex){
        System.out.println("异常通知方法执行! 异常信息为:"+ex);
    }

最终通知

@After("execution(* *..service.*.doSome(..))")
    public void after(){
        System.out.println("最终通知方法执行!");
        System.out.println("最终方法的作用是,无论是否出现异常,都会执行该通知。类似try...catch中的finally代码块");
    }

基于AspectJ方式之配置文件的方式通知声明

通知类的声明


public class MyAspect {
    //该注解表明当前方法是前置通知方法
    /*
    public void before(){
        System.out.println("前置通知方法执行!");
    }
    public void before(JoinPoint jp){
        System.out.println("前置通知方法执行!jp="+jp);
    }
    */
    //该注解表明当前方法是后置通知方法
    /*
    public void afterReturning(Object result){
        System.out.println("后置通知方法执行! 目标方法的返回值是"+result);
    }
    */
    //该注解表明当前方法是环绕通知方法
    /*
    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        System.out.println("环绕通知:目标方法执行之前!");
        String result = (String) pjp.proceed();
        if(result!=null){
            result = result.toUpperCase();
            
        }
        System.out.println("环绕通知:目标方法执行之后!");
        return result;
    }
    */
    //该注解表明当前方法是异常通知方法
    /*
    public void throwing(Exception ex){
        System.out.println("异常通知方法执行! 异常信息为:"+ex);
    }
    */
    //该注解表明当前方法是最终通知方法
    
    public void after(){
        System.out.println("最终通知方法执行!");
    }
    
}

配置文件的声明

<?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
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 注册目标类 -->
    <bean id="someServiceImpl" class="com.bjsxt.service.impl.SomeServiceImpl"></bean>
    <!-- 注册切面 -->
    <bean id="myAspect" class="com.bjsxt.aspects.MyAspect"></bean>
    <!-- AOP配置 -->
    <aop:config>
        <!-- 定义切入点 -->
        <aop:pointcut expression="execution(* *..service.*.doSome(..))" id="doSomePC"/>
        <aop:pointcut expression="execution(* *..service.*.doOther(..))" id="doOtherPC"/>
        <aop:aspect ref="myAspect">
            <!-- <aop:before method="before" pointcut-ref="doSomePC"/> -->
            <!-- <aop:before method="before(org.aspectj.lang.JoinPoint)" pointcut-ref="doSomePC"/> -->
            <!-- <aop:after-returning method="afterReturning(java.lang.Object)" pointcut-ref="doOtherPC" returning="result"/> -->
            <!-- <aop:around method="around" pointcut-ref="doOtherPC"/> -->
            <!-- <aop:after-throwing method="throwing(java.lang.Exception)" pointcut-ref="doSomePC" throwing="ex"/> -->
            <aop:after method="after" pointcut-ref="doSomePC"/>
        </aop:aspect>
    </aop:config>
    
</beans>

五、Spring的事物管理

事物的ACID特性

特性 介绍
原子性(Atomicity) 一个事务里面所有包含的SQL语句是一个执行整体,不可分割,要么都做,要么都不做。
一致性(Consistency) 事务开始时,数据库中的数据是一致的,事务结束时,数据库的数据也应该是一致的。
隔离性(Isolation) 是指数据库允许多个并发事务同时对其中的数据进行读写和修改的能力,隔离性可以防止事务的并发执行时,由于他们的操作命令交叉执行而导致的数据不一致状态。
持久性 (Durability) : 是指当事务结束后,它对数据库中的影响是永久的,即便系统遇到故障的情况下,数据也不会丢失。

DataSourceTransactionManager与HibernateTransactionManager

名称 区别
DataSourceTransactionManager 此事务管理器是针对传统的JDBC进行事务管理,在spring中是对JdbcTemplate进行事务管理
HibernateTransactionManager 是对Hibernate进行事务管理,当在spring中使用HibernateTemplate时,要使用此管理器。

注:当在service的一个方法中同时使用了JdbcTemplate和HibernateTemplate时,就要使用HibernateTransactionManager了,因为当使用DataSourceTransactionManager时,JdbcTemplate和HibernateTemplate获得的connection并不是同一个,也就没办法对service的方法进行事务管理了。

TransactionDefinition接口

Spring的TransactionDefinition接口中定义了如下事务相关常量

常量名 | 作用

int getPropagationBehavior(); 返回事务的传播行为
int getIsolationLevel(); 返回事务的隔离级别,事务管理器根据它来控制另外一个事务可以看到本事务内的哪些数据
String getName(); 返回事务的名字
int getTimeout(); 返回事务必须在多少秒内完成
boolean isReadOnly(); 返回是否优化为只读事务。

事物的传播行为

当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。
例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。

TransactionDefinition定义中包括了如下几个表示传播行为的常量:

常量 作用
TransactionDefinition.PROPAGATION_REQUIRED: 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
TransactionDefinition.PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。

不支持当前事务的情况:

常量 作用
TransactionDefinition.PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER: 以非事务方式运行, 如果当前存在事务,则抛出异常。

其他情况

常量 作用
TransactionDefinition.PROPAGATION_NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED(创建一个新的事务)。
相关文章
|
21天前
|
缓存 Java 开发工具
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
三级缓存是Spring框架里,一个经典的技术点,它很好地解决了循环依赖的问题,也是很多面试中会被问到的问题,本文从源码入手,详细剖析Spring三级缓存的来龙去脉。
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
|
21天前
|
缓存 安全 Java
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
从底层源码入手,通过代码示例,追踪AnnotationConfigApplicationContext加载配置类、启动Spring容器的整个流程,并对IOC、BeanDefinition、PostProcesser等相关概念进行解释
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
|
12天前
|
人工智能 开发框架 Java
重磅发布!AI 驱动的 Java 开发框架:Spring AI Alibaba
随着生成式 AI 的快速发展,基于 AI 开发框架构建 AI 应用的诉求迅速增长,涌现出了包括 LangChain、LlamaIndex 等开发框架,但大部分框架只提供了 Python 语言的实现。但这些开发框架对于国内习惯了 Spring 开发范式的 Java 开发者而言,并非十分友好和丝滑。因此,我们基于 Spring AI 发布并快速演进 Spring AI Alibaba,通过提供一种方便的 API 抽象,帮助 Java 开发者简化 AI 应用的开发。同时,提供了完整的开源配套,包括可观测、网关、消息队列、配置中心等。
562 7
|
9天前
|
XML 前端开发 Java
控制spring框架注解介绍
控制spring框架注解介绍
|
9天前
|
存储 NoSQL Java
Spring Session框架
Spring Session 是一个用于在分布式环境中管理会话的框架,旨在解决传统基于 Servlet 容器的会话管理在集群和云环境中的局限性。它通过将用户会话数据存储在外部介质(如数据库或 Redis)中,实现了会话数据的跨服务器共享,提高了应用的可扩展性和性能。Spring Session 提供了无缝集成 Spring 框架的 API,支持会话过期策略、并发控制等功能,使开发者能够轻松实现高可用的会话管理。
Spring Session框架
|
17天前
|
Java 应用服务中间件 开发者
深入探索并实践Spring Boot框架
深入探索并实践Spring Boot框架
27 2
|
17天前
|
机器学习/深度学习 数据采集 JavaScript
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
ADR药品不良反应监测系统是一款智能化工具,用于监测和分析药品不良反应。该系统通过收集和分析病历、处方及实验室数据,快速识别潜在不良反应,提升用药安全性。系统采用Java开发,基于SpringBoot框架,前端使用Vue,具备数据采集、清洗、分析等功能模块,并能生成监测报告辅助医务人员决策。通过集成多种数据源并运用机器学习算法,系统可自动预警药品不良反应,有效减少药害事故,保障公众健康。
ADR智能监测系统源码,系统采用Java开发,基于SpringBoot框架,前端使用Vue,可自动预警药品不良反应
|
26天前
|
运维 NoSQL Java
SpringBoot接入轻量级分布式日志框架GrayLog技术分享
在当今的软件开发环境中,日志管理扮演着至关重要的角色,尤其是在微服务架构下,分布式日志的统一收集、分析和展示成为了开发者和运维人员必须面对的问题。GrayLog作为一个轻量级的分布式日志框架,以其简洁、高效和易部署的特性,逐渐受到广大开发者的青睐。本文将详细介绍如何在SpringBoot项目中接入GrayLog,以实现日志的集中管理和分析。
104 1
|
1月前
|
缓存 Java 应用服务中间件
随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架
【9月更文挑战第6天】随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架。Nginx作为高性能的HTTP反向代理服务器,常用于前端负载均衡,提升应用的可用性和响应速度。本文详细介绍如何通过合理配置实现Spring Boot与Nginx的高效协同工作,包括负载均衡策略、静态资源缓存、数据压缩传输及Spring Boot内部优化(如线程池配置、缓存策略等)。通过这些方法,开发者可以显著提升系统的整体性能,打造高性能、高可用的Web应用。
58 2
|
1月前
|
Cloud Native 安全 Java
Micronaut对决Spring Boot:谁是微服务领域的王者?揭秘两者优劣,选对框架至关重要!
【9月更文挑战第5天】近年来,微服务架构备受关注,Micronaut和Spring Boot成为热门选择。Micronaut由OCI开发,基于注解的依赖注入,内置多种特性,轻量级且启动迅速;Spring Boot则简化了Spring应用开发,拥有丰富的生态支持。选择框架需考虑项目需求、团队经验、性能要求及社区支持等因素。希望本文能帮助您选择合适的微服务框架,助力您的软件开发项目取得成功!
99 2
下一篇
无影云桌面