Spring 中的声明式事务管理行为不可预测
我有一个带有声明式事务管理的 Spring+Hibernate 应用程序。 我有一个服务 (FooService
),它有 2 个公共方法 MethodA
和 MethodB
。客户端将调用
MethodA
,而MethodA
又将调用MethodB
。
Client -> MethodA -> MethodB
我希望事务仅从 MethodB 开始。 这是我的 spring 应用程序上下文中的片段:
<bean id="FooService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager" />
<property name="target" ref="FooServiceTarget" />
<property name="transactionAttributes">
<props>
<prop key="MethodB">PROPAGATION_REQUIRED,-FooException</prop>
</props>
</property>
</bean>
但是,当我从客户端调用 MethodA
时,它不会在调用 MethodB
时创建事务代理。 如果我将 MethodA
also 添加到应用程序上下文中的 bean 配置中,则会调用事务代理(按预期启动 MethodA
)。 为什么会这样呢?我可以实现仅从MethodB开始创建交易吗?
I have a Spring+Hibernate application with declarative transaction management.
I have a service (FooService
) which has 2 public methods MethodA
and MethodB
. The client will call
the MethodA
which in turn will call the MethodB
.
Client -> MethodA -> MethodB
I want the transaction to start only from MethodB onwards.
This is a snippet from my spring application-context:
<bean id="FooService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager" />
<property name="target" ref="FooServiceTarget" />
<property name="transactionAttributes">
<props>
<prop key="MethodB">PROPAGATION_REQUIRED,-FooException</prop>
</props>
</property>
</bean>
However, when I invoke the MethodA
from my client, it doesn't create a transaction proxy when MethodB
is to be called.
If I add MethodA
also to the bean configuration in application-context, the transaction proxy is invoked (starting MethodA
, as expected).
Why is this so? Can I achieve transaction being created only from MethodB onwards?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是行不通的。方法 A 和方法 B 位于同一代理内。
唯一正确的做法是将方法 B 移至不同的 Bean 中。
顺便说一句:这个问题之前已经被问过很多次了,这里是我之前的一些答案:
This can't work. Method A and Method B are inside the same proxy.
The only proper thing to do is to move method B into a different Bean.
BTW: this has been asked many times before, here are some previous answers of mine:
仅当您 使用 AspectJ使用 Spring 进行字节码编织。
Spring默认的AOP机制是JDK动态代理,它创建一个单独的 Proxy 实例来实现您的服务接口。该代理被注入到其他 bean 中代替您的服务,并且通过它的所有调用都将在委托给您的服务之前执行事务处理。由于从服务到自身的调用不通过代理,因此不能或不会启动任何事务。通过 AspectJ 字节码编织,事务代码将直接编织到您的服务中,并且它将正常工作。但是,如果您发现自己需要它来实现此目的,那么您很有可能需要将您的“服务”重构为至少两个独立的对象,因为这是一个信号,表明您在其中混合了关注点和/或交叉了抽象层。一节课。
Only if you use AspectJ bytecode weaving with Spring.
Spring's default AOP mechanism is JDK dynamic proxies, which creates a separate Proxy instance that implements your service interface. This proxy is injected into other bean in place of your service, and all calls that go through it will do the transaction stuff before delegating to your service. Since a call from your service to itself doesn't go through the proxy, no transaction can or will be started. With AspectJ bytecode weaving, the transaction code will be woven directly into your service, and it will work fine. If you find yourself needing it for this purpose, though, it's a good bet that you need to refactor your "service" into at least two, separate objects because it's a signal that you've mixed up concerns and/or crossed abstraction layers in one class.