Spring - @Transactional - What happens in background?
我想知道当你用
但是,我有以下疑问:
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', i.e. 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 !
来源:http://static.spring source.org/spring/docs/2.0.x/reference/transaction.html
为什么只有外部方法调用在事务中,而不是自调用方法?
这是一个大话题。Spring参考文档为此编写了多个章节。我建议阅读面向方面编程和事务处理方面的知识,因为Spring的声明性事务支持在AOP的基础上使用AOP。
但是在非常高的层次上,Spring为那些在类本身或成员上声明@transactional的类创建代理。代理在运行时大部分是不可见的。它为Spring提供了一种将方法调用之前、之后或周围的行为注入被代理对象的方法。事务管理只是可以被钩住的行为的一个例子。安全检查是另一回事。您也可以为日志之类的事情提供自己的服务。因此,当用@transactional注释一个方法时,Spring会动态创建一个代理,该代理实现与要注释的类相同的接口。当客户机调用您的对象时,调用会被截获,并通过代理机制注入行为。
顺便说一下,EJB中的事务工作原理类似。
正如您所观察到的,通过,代理机制只在从某个外部对象传入调用时工作。当您在对象中进行内部调用时,您实际上是通过"this"引用进行调用,这将绕过代理。然而,有很多方法可以解决这个问题。我在本论坛文章中解释了一种方法,在这种方法中,我使用beanfactoryPostProcessor在运行时将代理的实例注入到"自引用"类中。我将这个引用保存到一个名为"me"的成员变量中。然后,如果我需要进行需要更改线程事务状态的内部调用,那么我将通过代理(例如"me.somemethod()")来引导调用,论坛帖子将对此进行更详细的解释。请注意,BeanFactoryPostProcessor代码现在有点不同,因为它是在Spring1.x时间框架中写回的。但希望它能给你一个想法。我有一个更新的版本,我可能可以提供。
当Spring加载bean定义并配置为查找@transactional注释时,它将围绕实际bean创建这些代理对象。这些代理对象是运行时自动生成的类的实例。当调用方法时,这些代理对象的默认行为只是在"目标"bean(即您的bean)上调用相同的方法。
但是,代理也可以与拦截器一起提供,当存在拦截器时,代理将在调用目标bean的方法之前调用这些拦截器。对于用@transactional注释的目标bean,Spring将创建一个TransactionInterceptor,并将其传递给生成的代理对象。因此,当您从客户机代码调用该方法时,您将在代理对象上调用该方法,该对象首先调用TransactionInterceptor(它开始一个事务),然后在目标bean上调用该方法。调用完成后,TransactionInterceptor将提交/回滚该事务。它对客户端代码是透明的。
至于"外部方法",如果bean调用自己的方法之一,那么它将不会通过代理来这样做。记住,Spring将bean包装在代理中,您的bean不知道这一点。只有来自"外部"bean的调用才能通过代理。
这有帮助吗?
作为一个视觉上的人,我喜欢用代理模式的序列图来衡量。如果你不知道怎么读箭头,我读了第一个箭头:
(我被允许张贴照片,条件是我提到了照片的来源。作者:Noel Vaes,网址:www.noel vaes.eu)
最简单的答案是,在您声明@transactional的任何方法上,事务的边界在方法完成时开始,边界在方法完成时结束。
如果您使用的是JPA调用,那么所有提交都在这个事务边界中。假设您正在保存entity1、entity2和entity3。现在,在保存Entity3时发生异常,因为Enitiy1和Entity2在同一事务中,所以Entity1和Entity2将使用Entity3回滚。
事务:(entity1.save,entity2.save,entity3.save)。任何异常都将导致数据库中所有JPA事务的回滚。Spring在内部使用JPA事务。