[英]Spring @Autowired fields - which access modifier, private or package-private?
假設我們在類中的各個字段上使用@Autowired
注釋,並且我們沒有編寫也可以設置字段的 setter 或構造函數。
問題 - 訪問修飾符應該是什么, private
或package-private
(即無)?
例如:
public class MyClass {
@Autowired
private MyService myService;
}
對比
public class MyClass {
@Autowired
MyService myService;
}
在第一種情況下( private
字段)Spring 使用反射來連接字段,即使它沒有設置器。
第二種情況( package-private
字段)允許我們在需要擴展類以進行測試時訪問這些字段(例如,設置模擬)。
所以這兩種情況都可以正常工作,但更推薦哪種情況,特別是在測試方面?
所以這兩種情況都可以正常工作,但更推薦哪種情況,特別是在測試方面?
我認為這些屬性應該是private
:
@Autowired
private MyService myService;
因為使用 getter 方法來提供對屬性的訪問而不是允許其他類直接訪問它們總是好的。
而對於測試的目的,注射mocks
的private properties
的工作方式為相同的package-private
性質。
例如,使用Mockito
,您可以將private MyService
的模擬注入MyClass
如下所示:
public class MyClassTest {
@Mock
MyService service;
@InjectMocks
MyClass serv = new MyClass();
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
}
我通常更喜歡將字段設為私有並使用 setter 注入:
public class MyClass {
private MyService myService;
@Autowired
public void setMyService(MyService myService) {
this.myService = myService;
}
}
允許服務@Autowired,但設置為單元測試的模擬實例。
第一種情況還允許您根據框架注入模擬。 例如使用@InjectMocks
注釋。 您在 Spring 測試中也有ReflectionTestUtils.setField
,...
我個人不太喜歡為了測試目的而過多地修改類,所以我會選擇第一種情況。 但歸根結底,這主要取決於您首選的測試框架。
我通常不會將 @Autowired 用於私有字段或方法。 @Autowired 的意思是,外面的人會設置這個字段。 另一方面,“私有”意味着除了這個類之外沒有人被允許使用它。
如果 JIT 編譯器以某種方式優化此代碼,理論上混合 @Autowired 和私有會導致問題。 它可能是與 Java 內存模型並發相關的問題,這將是僅限生產且無法重現的。
我會讓 Autowired 字段至少包可見。 作為免費獎勵,它將允許在沒有技巧和變通方法的情況下編寫單元測試。
更新:此外,我會將此類字段聲明為volatile
以避免與 Java 內存模型相關的可見性沖突。 Spring 開發人員做了一些技巧來使自動裝配的字段在不顯式同步訪問的情況下工作,但我不確定這些技巧在任何硬件上的任何 JVM 中都能順利運行。
我寧願在 @Autowired 字段上使用 private ,原因如下:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.