春季-@Transactional-后台会发生什么?

本文翻译自:Spring - @Transactional - What happens in background?

I want to know what actually happens when you annotate a method with @Transactional ? 我想知道在使用@Transactional注释方法时实际发生了什么? Of course, I know that Spring will wrap that method in a Transaction. 当然,我知道Spring将把该方法包装在Transaction中。

But, I have the following doubts: 但是,我有以下疑问:

  1. I heard that Spring creates a proxy class ? 听说Spring创建了代理类 Can someone explain this in more depth . 有人可以更深入地解释这一点。 What actually resides in that proxy class? 该代理类中实际包含什么? What happens to the actual class? 实际班级会怎样? And how can I see Spring's created proxied class 我怎么能看到Spring创建的代理类
  2. I also read in Spring docs that: 我还在Spring文档中读到:

Note: Since this mechanism is based on proxies, only 'external' method calls coming in through the proxy will be intercepted . 注意:由于此机制基于代理, 因此将仅拦截通过代理传入的“外部”方法调用 This means that 'self-invocation', ie a method within the target object calling some other method of the target object, won't lead to an actual transaction at runtime even if the invoked method is marked with @Transactional ! 这意味着“自调用”,即目标对象中的一种调用目标对象其他方法的方法,即使被调用的方法标有@Transactional ,也不会在运行时导致实际事务!

Source: http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html 资料来源: http : //static.springsource.org/spring/docs/2.0.x/reference/transaction.html

Why only external method calls will be under Transaction and not the self-invocation methods? 为什么只有外部方法调用将在事务下而不是自调用方法下?


#1楼

参考:https://stackoom.com/question/4buD/春季-Transactional-后台会发生什么


#2楼

This is a big topic. 这是一个大话题。 The Spring reference doc devotes multiple chapters to it. Spring参考文档对此进行了专门的介绍。 I recommend reading the ones on Aspect-Oriented Programming and Transactions , as Spring's declarative transaction support uses AOP at its foundation. 我建议阅读有关面向方面的编程事务的内容 ,因为Spring的声明性事务支持使用AOP作为基础。

But at a very high level, Spring creates proxies for classes that declare @Transactional on the class itself or on members. 但是在非常高的层次上,Spring为在类本身或成员上声明@Transactional的类创建代理。 The proxy is mostly invisible at runtime. 代理在运行时几乎不可见。 It provides a way for Spring to inject behaviors before, after, or around method calls into the object being proxied. 它为Spring提供了一种方法,可以在方法调用之前,之后或周围将行为注入到要代理的对象中。 Transaction management is just one example of the behaviors that can be hooked in. Security checks are another. 事务管理只是可以挂接到的行为的一个示例。安全检查是另一个。 And you can provide your own, too, for things like logging. 您也可以提供自己的日志记录之类的东西。 So when you annotate a method with @Transactional , Spring dynamically creates a proxy that implements the same interface(s) as the class you're annotating. 因此,当您使用@Transactional注释方法时,Spring动态创建一个代理,该代理实现与要注释的类相同的接口。 And when clients make calls into your object, the calls are intercepted and the behaviors injected via the proxy mechanism. 当客户端对您的对象进行调用时,这些调用将被拦截,并通过代理机制注入行为。

Transactions in EJB work similarly, by the way. 顺便说一下,EJB中的事务工作类似。

As you observed, through, the proxy mechanism only works when calls come in from some external object. 如您所见,通过代理机制,仅当调用是从某个外部对象传入时才起作用。 When you make an internal call within the object, you're really making a call through the " this " reference, which bypasses the proxy. 在对象内进行内部调用时,实际上是通过“ this ”引用进行调用, 引用绕过了代理。 There are ways of working around that problem, however. 但是,有一些方法可以解决该问题。 I explain one approach in this forum post in which I use a BeanFactoryPostProcessor to inject an instance of the proxy into "self-referencing" classes at runtime. 我在此论坛帖子中解释了一种方法,其中使用BeanFactoryPostProcessor在运行时将代理实例注入“自引用”类中。 I save this reference to a member variable called " me ". 我将此引用保存到一个名为“ me ”的成员变量。 Then if I need to make internal calls that require a change in the transaction status of the thread, I direct the call through the proxy (eg " me.someMethod() ".) The forum post explains in more detail. 然后,如果需要进行需要更改线程事务状态的内部调用,则可以通过代理将调用定向(例如“ me.someMethod() ”。)。 Note that the BeanFactoryPostProcessor code would be a little different now, as it was written back in the Spring 1.x timeframe. 请注意, BeanFactoryPostProcessor代码现在将有所不同,因为它是在Spring 1.x时间范围内写回的。 But hopefully it gives you an idea. 但希望它能给您一个想法。 I have an updated version that I could probably make available. 我有一个可能会提供的更新版本。


#3楼

When Spring loads your bean definitions, and has been configured to look for @Transactional annotations, it will create these proxy objects around your actual bean . 当Spring加载您的bean定义并配置为查找@Transactional批注时,它将在您实际的bean周围创建这些代理对象 These proxy objects are instances of classes that are auto-generated at runtime. 这些代理对象是在运行时自动生成的类的实例。 The default behaviour of these proxy objects when a method is invoked is just to invoke the same method on the "target" bean (ie your bean). 调用方法时,这些代理对象的默认行为只是在“目标” bean(即您的bean)上调用相同的方法。

However, the proxies can also be supplied with interceptors, and when present these interceptors will be invoked by the proxy before it invokes your target bean's method. 但是,代理也可以提供拦截器,如果存在,这些拦截器将在代理调用目标bean的方法之前由代理调用。 For target beans annotated with @Transactional , Spring will create a TransactionInterceptor , and pass it to the generated proxy object. 对于使用@Transactional注释的目标bean,Spring将创建一个TransactionInterceptor ,并将其传递给生成的代理对象。 So when you call the method from client code, you're calling the method on the proxy object, which first invokes the TransactionInterceptor (which begins a transaction), which in turn invokes the method on your target bean. 因此,当您从客户端代码调用该方法时,您是在代理对象上调用该方法,该对象首先调用TransactionInterceptor (开始事务),然后又在目标bean上调用该方法。 When the invocation finishes, the TransactionInterceptor commits/rolls back the transaction. 调用完成后, TransactionInterceptor提交/回滚事务。 It's transparent to the client code. 对客户端代码透明。

As for the "external method" thing, if your bean invokes one of its own methods, then it will not be doing so via the proxy. 至于“外部方法”,如果您的bean调用它自己的方法之一,那么它将不会通过代理来执行。 Remember, Spring wraps your bean in the proxy, your bean has no knowledge of it. 记住,Spring将您的bean包装在代理中,您的bean不了解它。 Only calls from "outside" your bean go through the proxy. 只有来自“外部” bean的调用才能通过代理。

Does that help? 有帮助吗?


#4楼

As a visual person, I like to weigh in with a sequence diagram of the proxy pattern. 作为一个有视觉感的人,我喜欢使用代理模式的序列图。 If you don't know how to read the arrows, I read the first one like this: Client executes Proxy.method() . 如果您不知道如何阅读箭头,我将这样阅读第一个箭头: Client执行Proxy.method()

  1. The client calls a method on the target from his perspective, and is silently intercepted by the proxy 客户端从他的角度调用目标上的方法,并被代理默默拦截
  2. If a before aspect is defined, the proxy will execute it 如果定义了before方面,则代理将执行它
  3. Then, the actual method (target) is executed 然后,执行实际的方法(目标)
  4. After-returning and after-throwing are optional aspects that are executed after the method returns and/or if the method throws an exception 后返回和后抛出是可选的方面,在方法返回和/或方法抛出异常后执行
  5. After that, the proxy executes the after aspect (if defined) 之后,代理将执行after方面(如果已定义)
  6. Finally the proxy returns to the calling client 最后,代理返回到调用方客户端

代理模式序列图(I was allowed to post the photo on condition that I mentioned its origins. Author: Noel Vaes, website: www.noelvaes.eu) (允许我发布照片,但条件是提及其起源。作者:Noel Vaes,网站:www.noelvaes.eu)


#5楼

The simplest answer is: 最简单的答案是:

On whichever method you declare @Transactional the boundary of transaction starts and boundary ends when method completes. 在声明@Transactional的任何方法上,事务的边界开始,方法完成时边界结束。

If you are using JPA call then all commits are with in this transaction boundary . 如果您正在使用JPA调用,则所有提交都在此事务边界内

Lets say you are saving entity1, entity2 and entity3. 假设您正在保存entity1,entity2和entity3。 Now while saving entity3 an exception occur , then as enitiy1 and entity2 comes in same transaction so entity1 and entity2 will be rollback with entity3. 现在,在保存entry3 时发生了一个异常 ,然后当enitiy1和entity2进入同一事务时,entity1和entity2将与entry3 回滚

Transaction : 交易:

  1. entity1.save 实体1.保存
  2. entity2.save 实体2.保存
  3. entity3.save 实体3.保存

Any exception will result in rollback of all JPA transactions with DB.Internally JPA transaction are used by Spring. 任何异常都将导致所有JPA事务与数据库回滚.Spring内部使用JPA事务。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值