簡體   English   中英

Spring Java配置,@ Autowire與構造函數注入,@ Transaction和CGLIB

[英]Spring Java config, @Autowire vs. Constructor Injection, @Transactional and CGLIB

我們一直在使用@Autowired和基於Java的Spring配置取得了一些成功,但現在我們失去了控制權。 每個人都開始在任何地方添加自動連接的依賴項,創建周期和奇怪的錯誤。

所以我們正在考慮使用構造函數注入和Spring配置的自動裝配。

舊:

class Bean {
   @Autowired Foo foo;
}

@Configuration
@Import( FooCfg.class )
class BeanCfg {
   @Bean public Bean bean() { return new Bean(); }
}

新:

class Bean {
   public Bean(Foo foo) {...}
}

@Configuration
class BeanCfg {
   @Autowired FooCfg fooCfg;
   @Bean public Bean bean() { return new Bean(fooCfg.foo()); }
}

這非常有效(並且它驅使人們分割bean而不是創建具有10個以上構造函數參數的怪物)。

但是當Bean有一個使用@Transactional注釋的方法時失敗,因為CGLIB然后嘗試創建一個失敗的代理,因為它找不到無參數的構造函數。

這是什么解決方案?

您有幾種可能的解決方案

  1. 介紹您的類的接口
  2. 將Spring版本升級到至少4.0
  3. 添加protected無參數構造函數

介紹接口

在為類引入接口時,可以刪除CgLib的用法。 然后Spring將能夠使用JDK Dynamic Proxies來解決接口問題。 它圍繞一個已經存在的bean實例創建一個代理,該代理實現了它所包裝的類的所有接口。 這樣,你的類是否有一個無參數構造函數並不重要。

升級到Spring 4

在Spring 4.0中,添加了支持以允許使用缺少的無參數構造函數來代理類(參見SPR-10594 )。 為了實現Spring版本的升級並將Objenesis添加到類路徑中,Spring 4附帶了自己的重新打包的cglib版本,因此不再需要它了。

需要注意的一點是,如果你在構造函數中進行空檢查或初始化邏輯,你應該有一個沒有邏輯的構造函數,在cglib創建實例的情況下它可能會失敗。 我懷疑它將null傳遞給所有構造函數參數(或者一些默認的基元)。

添加了protected無參數構造函數

Cglib需要能夠創建一個用於包裝實際類的實例。 在類中有一個protected構造函數就足夠了,這樣cglib就可以調用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM