[英]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.