Spring交易可见性

在初始化应用程序上下文时,Spring遇到带有@Transactional标记的类时会创建代理。 @Transactional可以应用于类级别或方法级别。 在类级别应用它意味着该类中定义的所有公共方法都是事务性的。 Spring创建的代理类型,即Jdk代理或CGLIB代理,取决于将方法标记为事务性的类。 如果该类实现了至少一个接口,则Spring将创建一个Jdk动态代理。 该代理实现与原始类相同的接口,并使用事务维护逻辑拦截接口方法。 它将调用委托给其中组成的原始对象。 假设该类未实现任何接口,Spring将创建一个CGLIB代理。 该代理扩展了原始类并覆盖了公共方法。 我们将尽快对此进行仔细研究。 假设我们有一个这样定义的类:

public interface BookDao{void buyBook(String isbn) throws BookNotFoundException;Book findByIsbn(String isbn);int deductStock(Book book);
}public class JdbcBookDao implements BookDao{void buyBook(String isbn) throws BookNotFoundException{Book book = findByIsbn(isbn);if(book == null){throw new BookNotFoundException();}deductStock(book);}@Transactional(propagation=Propagation.REQUIRES_NEW)Book findByIsbn(String isbn){Book book = getJdbcTemplate().queryForObject("SELECT * FROM BOOK WHERE ISBN=?",ParameterizedBeanPropertyRowMapper.newInstance(Book.class), isbn);return book;}@Transactional(propagation=Propagation.REQUIRES_NEW)int deductStock(Book book){String sql = "UPDATE BOOK_STOCK SET STOCK=STOCK-1 WHERE BOOK_ID=?";return getJdbcTemplate().update(sql, stockIncrement, book.getId());}
}

现在,Spring是否会通过从main方法调用bookDao的findByIsbn自动创建交易? 否。我们必须在xml配置中声明这一点:

<tx:annotation-driven>

因此,如果它不创建事务,是否会引发错误? 答案还是不是。Spring非事务地执行此语句。

按照我们的预期,一旦声明了‹tx:annotation-driven›,Spring就会在该类实现接口时为JdbcBookDao创建一个Jdk动态代理。 现在说,我们调用JdbcBookDao的buyBook方法,Spring创建了多少个事务?

  1. 二:1用于findByIsbn,另外1用于deductStock。
  2. 一:在同一笔交易中同时找到findByIsbn和deductStock。
  3. 完全没有交易!

答案是(3)。 交易的默认交易模式是“代理”。 这意味着Spring仅考虑通过代理进行的方法调用进行自动事务管理。 现在,如果您仔细观察,buyBook方法不会标记为事务性的。 因此,当创建事务代理时,此方法不会被事务管理逻辑拦截,因为它没有标记为@Transactional。 简而言之,buyBook不会在代理中被覆盖。 因此,该方法直接在原始对象上调用。 因此,其他两个方法也将在原始对象上调用。 请记住,只有PROXY包含事务管理代码。 因此,当其他方法也被原始对象调用时,Spring根本不会创建事务。 现在,如果我们将buyBook标记为@Transactional,是否可以解决问题? Spring是否会为每个findByIsbn和deductStock方法创建两个单独的事务?

不会。在调用buyBook()时,Spring仅创建一个事务。 由于不会在原始对象本身而非代理上调用各个方法,因此不会进一步创建任何新事务。 那么如何解决这个问题呢?

我们可以要求Spring创建一个CGLIB proxy()吗? 现在,由于代理是具有重写的公共事务方法的子类,因此它为每个方法调用创建一个新事务? 再次没有。 CGLIB代理不会直接在超类上调用该方法。 这是一个大概的实现方法。

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;public class MyInterceptor implements MethodInterceptor {private Object realObject;public MyInterceptor(Object original) {this.realObject = original;}// This method will be called every time the object proxy calls any of its methodspublic Object intercept(Object o, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {/*** Transaction Management Code*/// Invoke the method on the real object with the given paramsObject res = method.invoke(realObject, args);/*** Transaction Management Code*/return res;}
}import net.sf.cglib.proxy.Enhancer;public class ProxyCreator(){public static T createProxy(T original){// Enhancer is CGLIB class which builds a dynamic proxy with new capabilitiesEnhancer e = new Enhancer();e.setSuperclass(original.getClass());// We have to declare the interceptor whose 'intercept' will be called when methods are called on proxy.e.setCallback(new MyInterceptor(original));T proxy = (T) e.create();return proxy;}
}

因此,如您在此处看到的,代理扩展了原始类并由其对象组成。 因此,当我们调用buyBook时,代理会创建一个事务并将该调用委托给原始对象。 从原始对象的buyBook中调用findByIsbn和deductStock不会,因此不会创建新交易。

一个快速的周转解决方案是,因为JdbcBookDao是一个单例,请从应用程序上下文中获取此对象。 现在,与其直接在对象上调用方法,不如使用引用来调用它(以确保调用代理),这就是方法的外观。

public class JdbcBookDao implements BookDao, ApplicationContextAware{private ApplicationContext context;private BookDao bookDao;public void setApplicationContext(ApplicationContext context){this.context = context;}public BookDao getBookDao(){bookDao = (BookDao)context.getBean("jdbcBookDao");}void buyBook(String isbn) throws BookNotFoundException{Book book = getBookDao().findByIsbn(isbn);if(book == null){throw new BookNotFoundException();}getBookDao().deductStock(book);}.....
}

刚刚实施了一个粗略的版本来使它正常工作。 我们绝对可以改进其设计方式。 与其直接将应用程序上下文注入DAO中,不如说我们可以使用一种辅助类来实现。 或完成此任务的另一种选择是使用程序化事务。

最后要注意的一点是,Spring仅在将公共方法标记为事务性时才管理事务。 对于私有,受保护和程序包私有的方法,Spring不提供事务管理支持。 对于动态代理,当它们实现接口时,所有事务处理方法都是公共的。 因此,无需担心非公开方法。 对于CGLIB代理,在创建子类时仅覆盖公共方法。 因此,即使在这里,也不会考虑非公开方法。

让我以一个问题结束这次讨论。 当我尝试使用‹tx:annotation-driven proxy-target-class =” true” /›代理目标类时,它实际上不起作用,即未创建CGLIB代理 。 为此,我必须进行一些小改动。 正如Spring文档明确指出的那样,如果在‹tx:annotation驱动的›,‹aop:config›或‹aop:aspectj-autoproxy›中的任何一个上启用了代理目标类,Spring将在容器上启用CGLIB代理创建。 因此,我刚刚创建了一个空的‹aop:config proxy-target-class =“ true” /›。 不用担心,它开始起作用! 不知道这是否是Spring本身的错误。 高度赞赏,如果有人可以回答这个问题。

参考: Spring交易可见性来自prasanthnath博客上的JCG合作伙伴 Prasanth Gullapalli。

翻译自: https://www.javacodegeeks.com/2013/11/spring-transactions-visibility.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/366784.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Axios 作弊表(Cheat Sheet)

英文原文链接 GET 请求 // Make a request for a user with a given ID axios.get(/user?ID12345).then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});// Optionally the request above could also be done as axios.get(…

loadrunner post请求

注意&#xff1a;loadrunner参数中的引号&#xff0c;需要自己加"\" post 请求&#xff0c;分为header 和body两个部分处理 header部分比较容易处理&#xff0c;使用函数实现&#xff0c;如web_add_header("pid","1")即可&#xff0c;具体参数可…

2018-2019-1 20165203 《信息安全系统设计基础》第六周学习总结

2018-2019-1 20165203 《信息安全系统设计基础》第六周学习总结 教材学习内容总结 重要知识点 I/O&#xff1a;在主存和外部设备&#xff08;例如磁盘存储器、终端和网络&#xff09;之间复制数据的过程。输入操作&#xff1a;从I/O设备复制数据到主存。输出操作&#xff1a;从…

linux 使用VI命令怎么删除输入内容,linux系统vi编辑器常用命令及使用方法。

在linux系统中编辑文档我们常用到vi编辑器。vi编辑器&#xff0c;通常称之为vi,是一种广泛存在于各种UNIX和Linux系统中的文本编辑程序。它的功能十分强大&#xff0c;但是命令繁多&#xff0c;不容易掌握&#xff0c;它可以执行输出、删除、查找、替换、块操作等众多文本操作&…

Spring安全–幕后

安全任务&#xff08;例如&#xff0c;用户身份验证和用户查看应用程序资源的授权&#xff09;通常由应用程序服务器处理。 可以将这些任务委托给Spring安全性流程&#xff0c;以减轻应用程序服务器处理这些任务的负担。 Spring安全性基本上通过实现标准javax.servlet.Filter来…

在react中使用svg的各种骚姿势

开头先抛个可供参考的项目ts-react-webpack4, 或脚手架steamer-react-ts 优势 SVG可被非常多的工具读取和修改(比如vscode)不失真, 放大缩小图像都很清晰SVG文件是纯粹的XML, 也是一种DOM结构使用方便, 设计软件可以直接导出 兼容性 上一张兼容性图表, 或到caniuse.com查看 …

chrome 浏览器的插件权限有多大?

转自&#xff1a;https://segmentfault.com/q/1010000003777353 1&#xff09;Chrome插件本身有机制控制&#xff0c;不会无限制的开放很多权限给你2&#xff09;页面的DOM元素时可以操作的&#xff0c;Chrome插件是和宿主页面之间是共享DOM对象&#xff0c;但是不共享Javascri…

3.2自定义方法

方法是类的一种行为&#xff0c;方会使我们的代码容易修改&#xff0c;方便阅读&#xff0c;实现封装和重用。比如前面使用的很多.net定义好的类的方法&#xff0c;当然我们也可以自定义方法。 3.2.1定义方法 语法&#xff1a; 访问修饰符 返回类型 方法名(参数列表) &#xff…

linux live cd ubuntu,在Windows 7上体验Ubuntu Live CD

http://download.gna.org/grub4dos/grub4dos-0.4.4.zip把grldr.mbr,grldr放到C盘根目录.注意:以管理员身份运行cmd,进行以下操作.备份/Boot/BCD:bcdedit /export "D:\BCD.backup"用bcdedit编辑启动文件/Boot/BCD添加GRUB引导项:bcdedit /create /d "GRUB" …

[Electron]仿写一个课堂随机点名小项目

自从前几个月下了抖音&#xff0c;无聊闲暇时就打会打开抖音&#xff0c;因为打开它有种莫名其妙打开了全世界的感觉... 无意中看到这个小视频&#xff1a;随机点名 于是仿写了一个课堂点名小项目&#xff0c;算是对Electron的一个简单的认识&#xff0c;有时间再深入。 项目…

何时以及如何使用ThreadLocal

正如我们的读者可能已经猜到的那样&#xff0c;我每天都在处理内存泄漏。 最近&#xff0c;一种特殊类型的OutOfMemoryError消息开始引起我的注意-滥用ThreadLocals触发的问题变得越来越频繁。 在查看此类泄漏的原因时&#xff0c;我开始相信其中一半以上是由于开发人员导致的&…

linux redis安装使用,linux安装redis

Linux(CentOS)中Redis介绍、安装、使用【一篇就够】2018-05-13 13:36:16 sjmz30071360 阅读数 1590更多分类专栏&#xff1a; redis版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循CC 4.0 BY-SA版权协议&#xff0c;转载请附上原文出处链接和本声明。一、介绍Redis is…

用three.js写一个简单的3D射门游戏

这个小游戏很简单&#xff0c;一共由3个部分构成。1个平面&#xff08;球场&#xff09;&#xff0c;1个球体&#xff08;足球&#xff09;还有一个立方体&#xff08;球门&#xff09;。 上个图给你们感受一下简陋的画风&#xff08;掘金最高上传5M图片&#xff0c;原来图片都…

100份Spring面试问答-最终名单(PDF下载)

上次更新时间&#xff1a;2019年2月11日 这是有关Spring框架的一些最重要问题的摘要&#xff0c;在面试或面试测试过程中可能会要求您回答这些问题&#xff01; 您无需担心下一次面试的机会&#xff0c;因为Java Code Geeks在这里为您服务&#xff01; 您可能会被问到的大多数…

3.1 unittest简介

3.1 unittest简介 前言 熟悉java的应该都清楚常见的单元测试框架Junit和TestNG。python里面也有单元测试框架-unittest,相当于是一个python版的junit。python里面的单元测试框架除了unittest&#xff0c;还有一个pytest框架&#xff0c;这个用的比较少&#xff0c;后面有空再继…

织梦其他模型使用联动类型地区联动

官方模型的联动类型只能模型是在【独立模型】或者官方默认的【分类信息】模型下使用&#xff0c;其他模型下使用无效&#xff0c;我们来让联动类型支持所有模型。 添加联动地区类型字段 内容模型管理 - 文章模型(或者其他模型) - 添加新字段 字段名称 和 数据类型 千万别搞错了…

linux修改组的选项名字为,Linux用户、组及权限管理浅析

一、用户和组1.用户系统用来认证(Authentication)&#xff0c;授权(Authorization)&#xff0c;审计(Autition)的帐号。通过登录用户来登录系统。操作系统通过登录不同的用户来调用相对应权限的进程或程序&#xff0c;也可以说&#xff0c;用户是能获取系统资源的权限集合。2.用…

如何在 vue-cli v3.0 中使用 SCSS/SASS

在项目中使用 SCSS/SASS 进行样式编写无疑会节省很多开发样式的时间。关于如何在 vue-cli v3.0 中使用 SCSS/SASS&#xff0c;这里提供三种方案。前提是在使用 vue-cli 生成项目时勾选了 CSS Pre-processors (CSS预处理器)&#xff0c;否则无法在项目中直接使用。 方案一&…

使用IntelliJ IDEA进行热部署

最近&#xff0c;在PrimeFaces论坛PrimeFaces IDE Poll中进行了投票&#xff0c;以投票赞成用于开发PrimeFaces应用程序的最佳IDE。 最多人投票支持NetBeans。 NetBeans和Eclipse是免费的IDE。 我最喜欢的IDE IntelliJ IDEA Ultimate不是免费的&#xff0c;我认为这就是为什么在…

创梦天地关嵩:借力腾讯云,打造文娱新生态——云+未来峰会回顾

欢迎大家前往腾讯云社区&#xff0c;获取更多腾讯海量技术实践干货哦~ 今年腾讯云未来峰会主题的关键词是“焕启”&#xff0c;这是包含无限希望的两个字&#xff0c;让人倍感振奋。“焕启”是什么意思&#xff1f;在我的理解中&#xff0c;“焕启”本身就是激活&#xff0c;激…