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