gpt4 book ai didi

java - 如何处理 Spring/EJB/Mockito... 代理上的内部调用?

转载 作者:IT老高 更新时间:2023-10-28 13:53:43 26 4
gpt4 key购买 nike

正如你所知道的,当你代理一个对象时,比如当你为 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 文档中对此进行了讨论:

http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-understanding-aop-proxies

有许多可能的解决方案。

重构您的类以避免绕过代理的自调用调用。

Spring 文档将其描述为 “最佳方法(此处使用的术语最好)”

这种方法的优点是简单,并且与任何框架都没有联系。但是,它可能不适合事务繁重的代码库,因为您最终会得到许多微不足道的小类。

在类内部获取对代理的引用。

这可以通过注入(inject)代理或使用硬编码的“AopContext.currentProxy()”调用来完成(参见上面的 Spring 文档)。

此方法允许您避免拆分类,但在许多方面否定了使用事务注释的优势。我个人的看法是,这是一种有点丑陋的东西,但丑陋是自包含的,如果使用大量交易,这可能是务实的做法。

切换到使用 AspectJ

由于 AspectJ 不使用代理,因此自调用不是问题

虽然这是一个非常干净的方法 - 它是以引入另一个框架为代价的。我参与了一个大型项目,正是出于这个原因引入了 AspectJ。

根本不要使用@Transactional

重构您的代码以使用手动事务划分 - 可能使用装饰器模式。

一个选项 - 但需要适度重构,引入额外的框架联系并增加复杂性 - 所以可能不是首选选项

我的建议

通常拆分代码是最好的答案,对于分离关注点也是一件好事。但是,如果我有一个严重依赖嵌套事务的框架/应用程序,我会考虑使用 AspectJ 来允许自调用。

关于java - 如何处理 Spring/EJB/Mockito... 代理上的内部调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8039041/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com