Spring 注解 @Resources, @Inject和@Autowired 的區別辨析

      網友投稿 878 2025-04-01

      @TOC


      本文簡述這三個spring應用里常用的注解區別。

      @Resources

      官方文檔里對@Resources的說明:

      The @Resource annotation is part of the JSR-250 annotation collection and is packaged with Jakarta EE.

      什么是JSR-250呢?訪問這個鏈接:https://jcp.org/en/jsr/detail?id=250

      里面有很多PDF可以下載:

      打開一看,其實就是Java支持的注解的文檔。這些文檔是最權威的:

      文檔里介紹,@Resources對Bean的注入按照如下的優先級進行:

      Match by Name

      Match by Type

      Match by Qualifier

      Match by Name

      我們來看看Match by name的例子。下面的代碼試圖通過Match by Name注入一個名稱為namedFile的Bean:

      @RunWith(springJUnit4ClassRunner.class) @ContextConfiguration( loader=AnnotationConfigContextLoader.class, classes=ApplicationContextTestResourceNameType.class) public class FieldResourceInjectionIntegrationTest { @Resource(name="namedFile") private File defaultFile; @Test public void givenResourceAnnotation_WhenOnField_ThenDependencyValid(){ assertNotNull(defaultFile); assertEquals("namedFile.txt", defaultFile.getName()); } }

      Bean的定義在如下代碼里:

      @Configuration public class ApplicationContextTestResourceNameType { @Bean(name="namedFile") public File namedFile() { File namedFile = new File("namedFile.txt"); return namedFile; } }

      運行時,申明Bean依賴處的@Resource的Name屬性和Bean定義處@Bean的Name屬性值一致,Match by Name測試通過。

      Match by Type

      將使用bean的消費者代碼里@Resource注解的name屬性去掉,使其變成下面這樣:

      @Resource private File defaultFile;

      測試仍然通過,是因為Match by Name的探測機制執行失敗后,進行下一輪Match by Type的探測,這一輪成功了。

      Match by Qualifier

      定義兩個Bean:

      @Configuration public class ApplicationContextTestResourceQualifier { @Bean(name="defaultFile") public File defaultFile() { File defaultFile = new File("defaultFile.txt"); return defaultFile; } @Bean(name="namedFile") public File namedFile() { File namedFile = new File("namedFile.txt"); return namedFile; } }

      測試代碼:

      @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( loader=AnnotationConfigContextLoader.class, classes=ApplicationContextTestResourceQualifier.class) public class QualifierResourceInjectionIntegrationTest { @Resource private File dependency1; @Resource private File dependency2; @Test public void givenResourceAnnotation_WhenField_ThenDependency1Valid(){ assertNotNull(dependency1); assertEquals("defaultFile.txt", dependency1.getName()); } @Test public void givenResourceQualifier_WhenField_ThenDependency2Valid(){ assertNotNull(dependency2); assertEquals("namedFile.txt", dependency2.getName()); } }

      這一次執行失敗,遇到異常org.springframework.beans.factory.NoUniqueBeanDefinitionException.

      原因是因為我們的測試代碼里,沒有指定注入Bean的名稱,因此Spring的Match by Name探測失敗,進行Match by Type時,探測到兩個類型一樣的Bean,Spring框架不知道注入哪一個,所以就報異常了。

      避免這個異常也很容易,使用@Qualifier.代碼如下:

      @Resource @Qualifier("defaultFile") private File dependency1; @Resource @Qualifier("namedFile") private File dependency2;

      @Inject

      Spring 注解 @Resources, @Inject和@Autowired 的區別辨析

      這個注解定義在JSR-330里,文檔鏈接:

      https://jcp.org/en/jsr/detail?id=330

      注入的優先級:

      Match by Type

      Match by Qualifier

      Match by Name

      Match by Type

      注意@Inject注入的最高優先級方式為Match by Type,而非@Resource的Match by Name.

      任意定義一個待注入的Component:

      @Component public class ArbitraryDependency { private final String label = "Arbitrary Dependency"; public String toString() { return label; } }

      使用@Inject注入:

      @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( loader=AnnotationConfigContextLoader.class, classes=ApplicationContextTestInjectType.class) public class FieldInjectIntegrationTest { @Inject private ArbitraryDependency fieldInjectDependency; @Test public void givenInjectAnnotation_WhenOnField_ThenValidDependency(){ assertNotNull(fieldInjectDependency); assertEquals("Arbitrary Dependency", fieldInjectDependency.toString()); } }

      Match by Qualifier

      定義一個新的待注入組件:

      public class AnotherArbitraryDependency extends ArbitraryDependency { private final String label = "Another Arbitrary Dependency"; public String toString() { return label; } }

      測試代碼:

      @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( loader=AnnotationConfigContextLoader.class, classes=ApplicationContextTestInjectQualifier.class) public class FieldQualifierInjectIntegrationTest { @Inject private ArbitraryDependency defaultDependency; @Inject private ArbitraryDependency namedDependency; @Test public void givenInjectQualifier_WhenOnField_ThenDefaultFileValid(){ assertNotNull(defaultDependency); assertEquals("Arbitrary Dependency", defaultDependency.toString()); } @Test public void givenInjectQualifier_WhenOnField_ThenNamedFileValid(){ assertNotNull(defaultDependency); assertEquals("Another Arbitrary Dependency", namedDependency.toString()); } }

      和之前@Resource的第一次試圖通過Match by Type注入一樣失敗,遇到異常:NoUniqueBeanDefinitionException

      利用@Qualifier避免這個異常:

      @Inject @Qualifier("defaultFile") private ArbitraryDependency defaultDependency; @Inject @Qualifier("namedFile") private ArbitraryDependency namedDependency;

      Match by Name

      public class YetAnotherArbitraryDependency extends ArbitraryDependency { private final String label = "Yet Another Arbitrary Dependency"; public String toString() { return label; } }

      消費者代碼:

      @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( loader=AnnotationConfigContextLoader.class, classes=ApplicationContextTestInjectName.class) public class FieldByNameInjectIntegrationTest { @Inject @Named("yetAnotherFieldInjectDependency") private ArbitraryDependency yetAnotherFieldInjectDependency; @Test public void givenInjectQualifier_WhenSetOnField_ThenDependencyValid(){ assertNotNull(yetAnotherFieldInjectDependency); assertEquals("Yet Another Arbitrary Dependency", yetAnotherFieldInjectDependency.toString()); } }

      application context代碼:

      @Configuration public class ApplicationContextTestInjectName { @Bean public ArbitraryDependency yetAnotherFieldInjectDependency() { ArbitraryDependency yetAnotherFieldInjectDependency = new YetAnotherArbitraryDependency(); return yetAnotherFieldInjectDependency; } }

      測試通過

      @Autowired

      這個注解和@Inject的用法一致,唯一區別就是@Autowired 屬于Spring框架提供的注解。例子略。

      Java Spring

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:WPS演示中的“隱藏幻燈片”功能
      下一篇:如何在Excel中查找頻率最高的值?
      相關文章
      亚洲男人天堂av| 亚洲视频在线观看免费| 亚洲日本一区二区三区在线| 亚洲av成人一区二区三区在线观看| 亚洲av无码片在线观看| 亚洲国产午夜精品理论片| 亚洲精品中文字幕无乱码| 亚洲视频在线观看不卡| 亚洲精品国产啊女成拍色拍| 亚洲精品国产肉丝袜久久| 亚洲国产精品综合久久久| 亚洲成a人片7777| 亚洲人成电影青青在线播放| 亚洲无圣光一区二区| 亚洲乱码卡一卡二卡三| 亚洲中文字幕日本无线码| ASS亚洲熟妇毛茸茸PICS| 亚洲中文字幕精品久久| 亚洲欧美国产日韩av野草社区| 亚洲精品久久无码av片俺去也 | 亚洲一区二区三区高清在线观看 | 亚洲国产婷婷六月丁香| 精品亚洲综合在线第一区| 亚洲精品午夜无码专区| 久久久亚洲欧洲日产国码农村| 亚洲丝袜美腿视频| 亚洲精品综合久久中文字幕| 亚洲一级毛片免观看| 亚洲熟妇av午夜无码不卡| www亚洲精品久久久乳| 亚洲精品成人在线| 国产亚洲福利精品一区| 亚洲日本中文字幕| 亚洲乱码一区av春药高潮| 亚洲欧美国产国产一区二区三区| 国产精品亚洲综合网站| 国内精品久久久久久久亚洲| 亚洲成av人片天堂网| 亚洲综合亚洲国产尤物| 亚洲午夜成人精品无码色欲| 国产精品亚洲综合天堂夜夜|