【问题标题】:Why Spring's @Transactional works without proxy?为什么 Spring 的 @Transactional 可以在没有代理的情况下工作?
【发布时间】:2019-02-07 09:40:47
【问题描述】:

我对 Spring 的 @Transactional 在内部如何工作很感兴趣,但是在我读到它的任何地方都有代理的概念。代理应该被自动装配以代替真正的 bean,并使用额外的事务处理方法“装饰”基本方法。 这个理论对我来说非常清楚并且非常有意义,所以我试图检查它是如何运作的。 我创建了一个带有基本控制器和服务层的 Spring Boot 应用程序,并用 @Transactional 注释标记了一个方法。服务如下所示:

public class TestService implements ITestService {

@PersistenceContext
EntityManager entityManager;

@Transactional
public void doSomething() {
    System.out.println("Service...");
    entityManager.persist(new TestEntity("XYZ"));
}}

控制器调用服务:

public class TestController {

@Autowired
ITestService testService;

@PostMapping("/doSomething")
public ResponseEntity addHero() {
    testService.doSomething();
    System.out.println(Proxy.isProxyClass(testService.getClass()));
    System.out.println(testService);
    return new ResponseEntity(HttpStatus.OK);
}}

一切正常,新实体被持久化到数据库中,但我关心的重点是输出:

Service...
false
com.example.demo.TestService@7fb48179

似乎是显式注入了服务类而不是代理类。不仅“isProxy”返回 false,而且类输出(“com.example.demo.TestService@7fb48179”)表明它不是代理。

你能帮我解决这个问题吗?为什么没有注入代理,没有代理它是如何工作的?有什么办法可以“强制”它被代理,如果是这样 - 为什么 Spring 默认不注入代理?

没有什么要补充的,这是一个非常简单的应用程序。应用程序属性也没有什么花哨的:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=superSecretPassword
spring.datasource.url=jdbc:mysql://localhost:3306/heroes?serverTimezone=UTC
spring.jpa.hibernate.ddl-auto=create-drop

提前谢谢你!

【问题讨论】:

    标签: java spring hibernate jpa transactional


    【解决方案1】:

    你的理解是正确的,但你的测试有缺陷:

    当 spring 文档说“代理”时,他们指的是模式,而不是特定的实现。 Spring 支持各种创建代理对象的策略。其中之一是您测试的java.lang.reflect.Proxy,但默认情况下,spring 使用更高级的技术,在运行时生成一个新的类定义,该类定义是服务的实际实现类的子类(并覆盖所有方法以应用事务建议)。您可以通过检查testService.getClass()(将引用该生成的类)或通过在调试器中停止执行并检查targetService 的字段来查看这一点。

    toString() 引用原始对象的原因是代理通过委托其目标对象实现toString(),目标对象使用其类名构建String

    【讨论】:

    • 非常感谢您的意见! .getClass() 返回 "class com.example.demo.TestService$$EnhancerBySpringCGLIB$$$1526bc9f" 所以现在一切都很好。
    猜你喜欢
    • 1970-01-01
    • 2016-11-27
    • 2018-07-15
    • 2016-01-30
    • 2015-09-06
    • 2017-03-08
    • 2013-08-25
    • 1970-01-01
    • 2019-02-27
    相关资源
    最近更新 更多