java - Spring - @Transactional - 在后台发生了什么?

标签 java spring spring-aop spring-jdbc transactional

我想知道当您使用 @Transactional 注释方法时实际发生了什么? 当然,我知道 Spring 会将该方法包装在 Transaction 中。

但是,我有以下疑问:

  1. 听说 Spring 创建了一个代理类?有人可以更深入解释这一点。 该代理类中实际存在什么?实际类(class)会发生什么?以及如何查看 Spring 创建的代理类
  2. 我还在 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', 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.springsource.org/spring/docs/2.0.x/reference/transaction.html

为什么 Transaction 下只有外部方法调用而不是自调用方法?

最佳答案

这是一个很大的话题。 Spring 引用文档用多个章节介绍它。我建议阅读 Aspect-Oriented Programming 上的内容和 Transactions ,因为 Spring 的声明式事务支持在其基础上使用 AOP。

但在非常高的层次上,Spring 为在类本身或成员上声明 @Transactional 的类创建代理。代理在运行时大部分是不可见的。它为 Spring 提供了一种在方法调用之前、之后或周围将行为注入(inject)被代理的对象的方法。事务管理只是可以 Hook 的行为的一个例子。安全检查是另一个例子。你也可以提供你自己的,比如日志记录。因此,当您使用 @Transactional 注释方法时,Spring 会动态创建一个代理,该代理实现与您正在注释的类相同的接口(interface)。并且当客户端调用你的对象时,调用会被拦截并通过代理机制注入(inject)行为。

顺便说一下,EJB 中的事务的工作方式类似。

正如您所观察到的,代理机制仅在调用来自某个外部对象时才起作用。当您在对象中进行内部调用时,您实际上是通过绕过代理的 this 引用进行调用。但是,有一些方法可以解决这个问题。我在 this forum post 中解释了一种方法在其中,我使用 BeanFactoryPostProcessor 在运行时将代理实例注入(inject)“自引用”类。我将此引用保存到名为me 的成员变量。然后,如果我需要进行需要更改线程事务状态的内部调用,我会通过代理直接调用(例如 me.someMethod()。)论坛帖子更详细地解释了.

请注意,BeanFactoryPostProcessor 代码现在会有所不同,因为它是在 Spring 1.x 时间范围内写回的。但希望它能给你一个想法。我有一个更新版本,我可能会提供。

关于java - Spring - @Transactional - 在后台发生了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1099025/

相关文章:

java - 如何使用适用于 Windows、Mac 和 Linux 的通用文件路径保存文件?

Java如何复制文件的一部分

Java 或 Spring : two-way encryption with salt?

java - Spring AOP异常处理如果存在catch block 则不执行建议

java - 有没有办法为我的主要 Activity 设定条件?

Java邮件: Only one part of the message is retrieved/Parsing error/Badly formatted mail

Spring MVC + 磁贴 : integration testing

java - 简单的 Spring MVC+安全设置

java - 私有(private)方法的方法拦截器

java - Eclipse:如何将Web项目转换为AspectJ项目并使用AJDT插件编织运行?