簡體   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