繁体   English   中英

为什么Spring的@Transactional在没有代理的情况下工作?

[英]Why Spring's @Transactional works without proxy?

我对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);
}}

整个过程都有效,新实体会持久保存到DB,但我关注的重点是输出:

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

先感谢您!

您的理解是正确的,但您的测试存在缺陷:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM