- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
正如你所知道的,当你代理一个对象时,比如当你为 Spring/EJB 创建一个具有事务属性的 bean 时,甚至当你使用某些框架创建一个部分模拟时,代理对象不知道这一点,并且内部调用不会被重定向,也不会被拦截...
这就是为什么如果你在 Spring 中做这样的事情:
@Transactionnal
public void doSomething() {
doSomethingInNewTransaction();
doSomethingInNewTransaction();
doSomethingInNewTransaction();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void doSomethingInNewTransaction() {
...
}
当您调用 doSomething 时,您希望在主事务之外还有 3 个新事务,但实际上,由于这个问题,您只能得到一个...
所以我想知道你是如何处理这些问题的......
我实际上处于必须处理复杂事务系统的情况,我认为没有比将服务拆分为许多小服务更好的方法了,这样我就可以确保通过所有代理。 ..
这让我很困扰,因为所有代码都属于同一个功能域,不应该拆分...
我发现这个相关问题的答案很有趣: Spring - @Transactional - What happens in background?
Rob H 说我们可以在服务内部注入(inject) spring 代理,然后调用 proxy.doSomethingInNewTransaction();反而。这很容易做到,而且很有效,但我真的不喜欢它......
侯云峰说:
So I write my own version of CglibSubclassingInstantiationStrategy and proxy creator so that it will use CGLIB to generate a real subclass which delegates call to its super rather than another instance, which Spring is doing now. So I can freely annotate on any methods(as long as it is not private), and from wherever I call these methods, they will be taken care of. Well, I still have price to pay: 1. I must list all annotations that I want to enable the new CGLIB sub class creation. 2. I can not annotate on a final method since I am now generating subclass, so a final method can not be intercepted.
他所说的“现在哪个 Spring 在做什么”是什么意思?这是否意味着内部事务调用现在被拦截了?
你觉得哪个更好?
当您需要一些事务粒度时,您会拆分类吗?还是您使用上述的一些解决方法? (请分享)
最佳答案
我将讨论 Spring 和 @Transactional,但该建议也适用于许多其他框架。
这是基于代理方面的固有问题。此处的 spring 文档中对此进行了讨论:
有许多可能的解决方案。
重构您的类以避免绕过代理的自调用调用。
Spring 文档将其描述为 “最佳方法(此处使用的术语最好)”。
这种方法的优点是简单,并且与任何框架都没有联系。但是,它可能不适合事务繁重的代码库,因为您最终会得到许多微不足道的小类。
在类内部获取对代理的引用。
这可以通过注入(inject)代理或使用硬编码的“AopContext.currentProxy()”调用来完成(参见上面的 Spring 文档)。
此方法允许您避免拆分类,但在许多方面否定了使用事务注释的优势。我个人的看法是,这是一种有点丑陋的东西,但丑陋是自包含的,如果使用大量交易,这可能是务实的做法。
切换到使用 AspectJ
由于 AspectJ 不使用代理,因此自调用不是问题
虽然这是一个非常干净的方法 - 它是以引入另一个框架为代价的。我参与了一个大型项目,正是出于这个原因引入了 AspectJ。
根本不要使用@Transactional
重构您的代码以使用手动事务划分 - 可能使用装饰器模式。
一个选项 - 但需要适度重构,引入额外的框架联系并增加复杂性 - 所以可能不是首选选项
我的建议
通常拆分代码是最好的答案,对于分离关注点也是一件好事。但是,如果我有一个严重依赖嵌套事务的框架/应用程序,我会考虑使用 AspectJ 来允许自调用。
关于java - 如何处理 Spring/EJB/Mockito... 代理上的内部调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8039041/
为了让我的代码几乎完全用 Jquery 编写,我想用 Jquery 重写 AJAX 调用。 这是从网页到 Tomcat servlet 的调用。 我目前情况的类似代码: var http = new
我想使用 JNI 从 Java 调用 C 函数。在 C 函数中,我想创建一个 JVM 并调用一些 Java 对象。当我尝试创建 JVM 时,JNI_CreateJavaVM 返回 -1。 所以,我想知
环顾四周,我发现从 HTML 调用 Javascript 函数的最佳方法是将函数本身放在 HTML 中,而不是外部 Javascript 文件。所以我一直在网上四处寻找,找到了一些简短的教程,我可以根
我有这个组件: import {Component} from 'angular2/core'; import {UserServices} from '../services/UserService
我正在尝试用 C 实现一个简单的 OpenSSL 客户端/服务器模型,并且对 BIO_* 调用的使用感到好奇,与原始 SSL_* 调用相比,它允许一些不错的功能。 我对此比较陌生,所以我可能会完全错误
我正在处理有关异步调用的难题: 一个 JQuery 函数在用户点击时执行,然后调用一个 php 文件来检查用户输入是否与数据库中已有的信息重叠。如果是这样,则应提示用户确认是否要继续或取消,如果他单击
我有以下类(class)。 public Task { public static Task getInstance(String taskName) { return new
嘿,我正在构建一个小游戏,我正在通过制作一个数字 vector 来创建关卡,该数字 vector 通过枚举与 1-4 种颜色相关联。问题是循环(在 Simon::loadChallenge 中)我将颜
我有一个java spring boot api(数据接收器),客户端调用它来保存一些数据。一旦我完成了数据的持久化,我想进行另一个 api 调用(应该处理持久化的数据 - 数据聚合器),它应该自行异
首先,这涉及桌面应用程序而不是 ASP .Net 应用程序。 我已经为我的项目添加了一个 Web 引用,并构建了各种数据对象,例如 PayerInfo、Address 和 CreditCard。但问题
我如何告诉 FAKE 编译 .fs文件使用 fsc ? 解释如何传递参数的奖励积分,如 -a和 -target:dll . 编辑:我应该澄清一下,我正在尝试在没有 MSBuild/xbuild/.sl
我使用下划线模板配置了一个简单的主干模型和 View 。两个单独的 API 使用完全相同的配置。 API 1 按预期工作。 要重现该问题,请注释掉 API 1 的 URL,并取消注释 API 2 的
我不确定什么是更好的做法或更现实的做法。我希望从头开始创建目录系统,但不确定最佳方法是什么。 我想我在需要显示信息时使用对象,例如 info.php?id=100。有这样的代码用于显示 Game.cl
from datetime import timedelta class A: def __abs__(self): return -self class B1(A):
我在操作此生命游戏示例代码中的数组时遇到问题。 情况: “生命游戏”是约翰·康威发明的一种细胞自动化技术。它由一个细胞网格组成,这些细胞可以根据数学规则生存/死亡/繁殖。该网格中的活细胞和死细胞通过
如果我像这样调用 read() 来读取文件: unsigned char buf[512]; memset(buf, 0, sizeof(unsigned char) * 512); int fd;
我用 C 编写了一个简单的服务器,并希望调用它的功能与调用其他 C 守护程序的功能相同(例如使用 ./ftpd start 调用它并使用 ./ftpd stop 关闭该实例)。显然我遇到的问题是我不知
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
在 dos 中,当我粘贴此命令时它会起作用: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
我希望能够从 cmd 在我的 Windows 10 计算机上调用 python3。 我已重新安装 Python3.7 以确保选择“添加到路径”选项,但仍无法调用 python3 并使 CMD 启动 P
我是一名优秀的程序员,十分优秀!