<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          @Autowired、@Resource和@Inject注解的區(qū)別(最詳細(xì))

          共 11130字,需瀏覽 23分鐘

           ·

          2021-01-06 15:05

          點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”

          優(yōu)質(zhì)文章,第一時(shí)間送達(dá)

          76套java從入門(mén)到精通實(shí)戰(zhàn)課程分享

          ?在Spring中依賴(lài)注入可以使用@Autowired、@Resource和@Inject來(lái)完成,并且在一般的使用中是可以相互替換的(注意是一般),不過(guò)三者還是有區(qū)別,今天來(lái)介紹一下他們的區(qū)別:

          ? ? ?如果你想更加深入的了解@Autowired、@Resource的區(qū)別,請(qǐng)移步:Spring源碼分析@Autowired、@Resource注解的區(qū)別,這里面可能是你見(jiàn)過(guò)最詳細(xì)的關(guān)于@Autowired、@Resource的區(qū)別,看完之后,面試你懂得。

          ? ? ?@Autowired注解:

          ? ? ? ? 1.Spring本身替換的注解(org.springframework.beans.factory.annotation.Autowired),需要導(dǎo)入Spring相應(yīng)的jar包才能使用

          ? ? ? ? 2.可以標(biāo)注的位置:構(gòu)造器、方法、方法參數(shù)、變量域和注解上面

          @Target({ElementType.CONSTRUCTOR,?ElementType.METHOD,?
          ElementType.PARAMETER,?ElementType.FIELD,?ElementType.ANNOTATION_TYPE})
          @Retention(RetentionPolicy.RUNTIME)
          @Documented
          public?@interface?Autowired?{
          ???boolean?required()?default?true;
          }

          ? ? ? ?3.在Spring容器解析@Autowired注解時(shí),使用的后置處理器為AutowiredAnnotationBeanPostProcessor,在這個(gè)后置處理的注釋中有這么一段:

          {@link?org.springframework.beans.factory.config.BeanPostProcessor?BeanPostProcessor}
          *?implementation?that?autowires?annotated?fields,?setter?methods,?and?arbitrary
          *?config?methods.?Such?members?to?be?injected?are?detected?through?annotations:
          *?by?default,?Spring's?{@link?Autowired?@Autowired}?and?{@link?Value?@Value}
          *?annotations.
          *
          *?

          Also?supports?JSR-330's?{@link?javax.inject.Inject?@Inject}?annotation,
          *?if?available,?as?a?direct?alternative?to?Spring's?own?{@code?@Autowired}.

          ? ? ? ? 4.?@Autowired注解有一個(gè)required屬性,當(dāng)指定required屬性為false時(shí),意味著在容器中找相應(yīng)類(lèi)型的bean,如果找不到則忽略,而不報(bào)錯(cuò)(這一條是兩個(gè)注解所沒(méi)有的功能)。

          ? ? ? ?5. 默認(rèn)優(yōu)先按照類(lèi)型去容器中找對(duì)應(yīng)的組件,找到就賦值,如果找到多個(gè)相同類(lèi)型的組件,再將屬性的名稱(chēng)作為組件的id去容器中查找,如果組件id對(duì)象的bean不存在,而且required屬性為true,就報(bào)錯(cuò)。

          ? ? ? ?6. 支持@Primary注解,讓Spring進(jìn)行自動(dòng)裝配的時(shí)候,默認(rèn)使用首選的bean;

          ? ? ? @Resource

          ? ? ? ? ?1.JSR250規(guī)范提供的注解(javax.annotation.Resource),不需要導(dǎo)入格外的包,這個(gè)注解在JDK的rt.jar包中

          ? ? ? ? ?2.可以標(biāo)注的位置:TYPE(表示可以標(biāo)注在接口、類(lèi)、枚舉),F(xiàn)IELD(變量域)和METHOD(方法)上面。

          @Target({TYPE,?FIELD,?METHOD})
          @Retention(RUNTIME)
          public?@interface?Resource?{
          ????String?name()?default?"";
          ?
          ????String?lookup()?default?"";
          ?
          ????Class?type()?default?java.lang.Object.class;
          ?
          ????enum?AuthenticationType?{
          ????????????CONTAINER,
          ????????????APPLICATION
          ????}
          ?
          ????AuthenticationType?authenticationType()?default?AuthenticationType.CONTAINER;
          ?
          ????boolean?shareable()?default?true;
          ?
          ????String?mappedName()?default?"";
          ?
          ????String?description()?default?"";
          }


          ? ? ? 3.在Spring容器解析@Resource注解時(shí),使用的后置處理器為CommonAnnotationBeanPostProcessor,在這個(gè)后置處理的注釋中有這么一段:?

          *?{@link?org.springframework.beans.factory.config.BeanPostProcessor}?implementation
          *?that?supports?common?Java?annotations?out?of?the?box,?in?particular?the?JSR-250
          *?annotations?in?the?{@code?javax.annotation}?package.?These?common?Java
          *?annotations?are?supported?in?many?Java?EE?5?technologies?(e.g.?JSF?1.2),
          *?as?well?as?in?Java?6's?JAX-WS.
          *
          *?

          This?post-processor?includes?support?for?the?{@link?javax.annotation.PostConstruct}
          *?and?{@link?javax.annotation.PreDestroy}?annotations?-?as?init?annotation
          *?and?destroy?annotation,?respectively?-?through?inheriting?from
          *?{@link?InitDestroyAnnotationBeanPostProcessor}?with?pre-configured?annotation?types.
          *
          *?

          The?central?element?is?the?{@link?javax.annotation.Resource}?annotation
          *?for?annotation-driven?injection?of?named?beans,?by?default?from?the?containing
          *?Spring?BeanFactory,?with?only?{@code?mappedName}?references?resolved?in?JNDI.
          *?The?{@link?#setAlwaysUseJndiLookup?"alwaysUseJndiLookup"?flag}?enforces?JNDI?lookups
          *?equivalent?to?standard?Java?EE?5?resource?injection?for?{@code?name}?references
          *?and?default?names?as?well.?The?target?beans?can?be?simple?POJOs,?with?no?special
          *?requirements?other?than?the?type?having?to?match.

          ? ? ? 4. 默認(rèn)是按照組件名稱(chēng)進(jìn)行裝配的

          ? ? ? ? ?這樣說(shuō)大家可能沒(méi)有很深的印象,為啥@Autowired是根據(jù)類(lèi)型,@Resource是根據(jù)組件名稱(chēng),下面使用代碼來(lái)進(jìn)行解釋?zhuān)? ? ? ? ?

          @Component
          public?class?Student?{
          ????private?String?num?=?"1";
          ????public?String?getNum()?{
          ????????return?num;
          ????}
          ????public?void?setNum(String?num)?{
          ????????this.num?=?num;
          ????}
          }
          @Configuration
          @ComponentScan(basePackages?=?{"it.cast.autowired"})
          public?class?Config?{
          ?
          ????@Bean
          ????public?Student?student1(){
          ????????Student?student?=?new?Student();
          ????????student.setNum("2");
          ????????return?student;
          ????}
          }
          @Component
          public?class?Teacher?{
          ?
          ????@Resource???//注意這里使用的@Resource注解,Spring支持注入Map、Conllent類(lèi)型的屬性變量
          ????private?Map?student;
          ????public?Map?getStudent()?{
          ????????return?student;
          ????}
          ?
          ????public?void?setStudent(Map?student)?{
          ????????this.student?=?student;
          ????}
          ?
          }
          public?class?Test01?{
          ????public?static?void?main(String[]?args)?{
          ????????AnnotationConfigApplicationContext?context?=?new?AnnotationConfigApplicationContext(Config.class);
          ????????Teacher?teacher?=?context.getBean(Teacher.class);
          ????????System.out.println(teacher.getStudent());
          ????}
          }
          ?
          //打印結(jié)果:
          //Caused?by:?org.springframework.beans.factory.BeanNotOfRequiredTypeException:?Bean?named?'student'?is?expected?to?be?of?type?'java.util.Map'?but?was?actually?of?type?'it.cast.autowired.Student'
          //?at?org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:392)
          //?at?org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:204)
          //?at?org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:452)
          //?at?org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:527)
          //?at?org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:497)
          //?at?org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:637)
          //?at?org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:180)
          //?at?org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
          //?at?org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:322)
          //?...?12?more
          ?

          ? ? ? ?可以看到使用@Resource標(biāo)注的Map類(lèi)型的時(shí)報(bào)錯(cuò),為什么報(bào)錯(cuò)?因?yàn)镸ap類(lèi)型的變量名為student,容器中已經(jīng)存在了名稱(chēng)為student的bean,其類(lèi)型為Student,所以會(huì)報(bào)錯(cuò),大致步驟為:根據(jù)組件名稱(chēng)student去Spring容器中獲取相應(yīng)的Bean,在獲取之后,會(huì)將獲取到的Bean賦值給相應(yīng)的屬性。

          ? ? ? 如果此時(shí)我們將@Resource換成@Autowired時(shí),其打印結(jié)果又會(huì)如何?

          @Component
          public?class?Student?{
          ????private?String?num?=?"1";
          ????public?String?getNum()?{
          ????????return?num;
          ????}
          ????public?void?setNum(String?num)?{
          ????????this.num?=?num;
          ????}
          }
          @Configuration
          @ComponentScan(basePackages?=?{"it.cast.autowired"})
          public?class?Config?{
          ?
          ????@Bean
          ????public?Student?student1(){
          ????????Student?student?=?new?Student();
          ????????student.setNum("2");
          ????????return?student;
          ????}
          }
          @Component
          public?class?Teacher?{
          ?
          ????@Autowired??//注意這里使用的@Autowired注解,Spring支持注入Map、Conllent類(lèi)型的屬性變量
          ????private?Map?student;
          ????public?Map?getStudent()?{
          ????????return?student;
          ????}
          ?
          ????public?void?setStudent(Map?student)?{
          ????????this.student?=?student;
          ????}
          ?
          }
          public?class?Test01?{
          ????public?static?void?main(String[]?args)?{
          ????????AnnotationConfigApplicationContext?context?=?new?AnnotationConfigApplicationContext(Config.class);
          ????????Teacher?teacher?=?context.getBean(Teacher.class);
          ????????System.out.println(teacher.getStudent());
          ????}
          }
          //其打印結(jié)果:
          //{student=it.cast.autowired.Student@61009542,?student1=it.cast.autowired.Student@77e9807f}


          ? ? ? 可以看到系統(tǒng)并沒(méi)有報(bào)錯(cuò),根據(jù)上面兩組代碼的對(duì)比,可以得出以下結(jié)論:當(dāng)使用@Resource注解時(shí),是根據(jù)組件名稱(chēng)進(jìn)行查找,當(dāng)使用@Autowired注解時(shí),是根據(jù)類(lèi)型進(jìn)行查找的。

          ? ? ? 5. 支持@Primary注解,不過(guò)首先按照會(huì)按照名稱(chēng)進(jìn)行注入bean,如果Spring IOC容器中沒(méi)有該Bean,則按照@Primary注解標(biāo)注的bean進(jìn)行裝配(這條是我自己總結(jié)的,別人都說(shuō)不支持,但是代碼是不會(huì)騙人的,給出驗(yàn)證代碼,如有錯(cuò)誤,請(qǐng)多指教,這個(gè)代碼的邏輯其實(shí)可以看一下CommonAnnotationBeanPostProcessor是怎么處理的,有時(shí)間我來(lái)看看源碼

          ? ? ?下面驗(yàn)證@Resource默認(rèn)是按照組件名稱(chēng)進(jìn)行裝配的和持支@Primary注解的:

          @Configuration
          @ComponentScan({"it.cast.resouce"})
          public?class?ResourceConfig?{
          ?
          ????@Primary???//標(biāo)有Primary注解,使用@Autowired@Inject注解注解時(shí),優(yōu)先被加載
          ????@Bean
          ????public?Y?y1(){
          ????????Y?y?=?new?Y();
          ????????y.setI(0);
          ????????return?y;
          ????}
          ?
          }
          ?
          @Component
          public?class?X?{
          ????@Resource???//這里使用的是@Resource注解,該注解默認(rèn)按照組件名稱(chēng)進(jìn)行裝配的,所以會(huì)優(yōu)先加載id為y的bean
          ????private?Y?y;
          ?
          ????public?Y?getY()?{
          ????????return?y;
          ????}
          ?
          ????public?void?setY(Y?y)?{
          ????????this.y?=?y;
          ????}
          }
          ?
          @Component
          public?class?Y?{
          ????private?int?i?=?2;
          ?
          ????public?int?getI()?{
          ????????return?i;
          ????}
          ?
          ????public?void?setI(int?i)?{
          ????????this.i?=?i;
          ????}
          }


          ? ? ? 測(cè)試一下使用,使用@Resource注解的打印結(jié)果:

          ????@Test
          ????public?void?ResourceConfigTest(){
          ????????AnnotationConfigApplicationContext?context?=
          ????????????????new?AnnotationConfigApplicationContext(ResourceConfig.class);
          ?
          ????????X?bean?=?context.getBean(X.class);
          ????????System.out.println(bean.getY().getI());
          ????}
          ????//輸出結(jié)果為:
          ????//?????2
          ????//從而驗(yàn)證了@Resource默認(rèn)按照名稱(chēng)進(jìn)行加載


          ? ? ?此時(shí),將@Resource注解的屬性名稱(chēng)換成y12,這個(gè)bean在容器里面沒(méi)有的

          @Configuration
          @ComponentScan({"it.cast.resouce"})
          public?class?ResourceConfig?{
          ?
          ????@Primary???//標(biāo)有Primary注解,使用@Autowired@Inject注解注解時(shí),優(yōu)先被加載
          ????@Bean
          ????public?Y?y1(){
          ????????Y?y?=?new?Y();
          ????????y.setI(0);
          ????????return?y;
          ????}
          ?
          }
          ?
          @Component
          public?class?X?{
          ????@Resource???????//這里使用的是@Resource注解,該注解默認(rèn)按照組件名稱(chēng)進(jìn)行裝配的,所以會(huì)優(yōu)先加載id為y12的bean,
          ????private?Y?y12;??//如果找不到則按Primary注解標(biāo)注的bean進(jìn)行注入
          ?
          ????public?Y?getY()?{
          ????????return?y12;
          ????}
          ?
          ????public?void?setY(Y?y)?{
          ????????this.y12?=?y;
          ????}
          }
          ?
          @Component
          public?class?Y?{
          ????private?int?i?=?2;
          ?
          ????public?int?getI()?{
          ????????return?i;
          ????}
          ?
          ????public?void?setI(int?i)?{
          ????????this.i?=?i;
          ????}
          }


          ? ? ? 測(cè)試一下使用,使用@Resource注解的打印結(jié)果:?

          ????@Test
          ????public?void?ResourceConfigTest(){
          ????????AnnotationConfigApplicationContext?context?=
          ????????????????new?AnnotationConfigApplicationContext(ResourceConfig.class);
          ?
          ????????X?bean?=?context.getBean(X.class);
          ????????System.out.println(bean.getY().getI());
          ????}
          ????//輸出結(jié)果為:
          ????//?????0
          ????//由于沒(méi)有找到id為y12的bean,所以注入了使用@Primary標(biāo)注的bean,
          ????//而且整個(gè)程序沒(méi)有報(bào)錯(cuò),所以驗(yàn)證了@Resource支持@Primary注解

          ? ? ? 此時(shí),將@Resource注解換成@Autowired注解的打印結(jié)果:

          @Configuration
          @ComponentScan({"it.cast.resouce"})
          public?class?ResourceConfig?{
          ?
          ????@Primary???//標(biāo)有Primary注解,使用@Autowired@Inject注解注解時(shí),優(yōu)先被加載
          ????@Bean
          ????public?Y?y1(){
          ????????Y?y?=?new?Y();
          ????????y.setI(0);
          ????????return?y;
          ????}
          ?
          }
          ?
          @Component
          public?class?X?{
          ????@Autowired???
          ????private?Y?y;??//此時(shí)不管名稱(chēng)是y還是y12,都會(huì)使用標(biāo)有Primary注解的bean
          ?
          ????public?Y?getY()?{
          ????????return?y;
          ????}
          ?
          ????public?void?setY(Y?y)?{
          ????????this.y?=?y;
          ????}
          }
          ?
          @Component
          public?class?Y?{
          ????private?int?i?=?2;
          ?
          ????public?int?getI()?{
          ????????return?i;
          ????}
          ?
          ????public?void?setI(int?i)?{
          ????????this.i?=?i;
          ????}
          }


          ? ? 測(cè)試一下使用,使用@Autowired注解的打印結(jié)果:?

          ????@Test
          ????public?void?ResourceConfigTest(){
          ????????AnnotationConfigApplicationContext?context?=
          ????????????????new?AnnotationConfigApplicationContext(ResourceConfig.class);
          ?
          ????????X?bean?=?context.getBean(X.class);
          ????????System.out.println(bean.getY().getI());
          ????}
          ????//輸出結(jié)果為:
          ????//?????0
          ????//從而驗(yàn)證了@Autowired支持@Primary注解

          ? ? ? @Inject

          ? ? ? ? ??1.JSR330規(guī)范提供的注解(javax.inject.Inject),主要導(dǎo)入javax.inject包才能使用

          ? ? ? ? ? 2.可以標(biāo)注的位置:方法、構(gòu)造器和變量域中

          @Target({?METHOD,?CONSTRUCTOR,?FIELD?})
          @Retention(RUNTIME)
          @Documented
          public?@interface?Inject?{}??//該注解中沒(méi)有任何屬性

          ? ? ? ? ?3.在Spring容器解析@Inject注解時(shí),使用的后置處理器和@Autowired是一樣的,都是AutowiredAnnotationBeanPostProcessor。

          ? ? ? ? ?4.由于@Inject注解沒(méi)有屬性,在加載所需bean失敗時(shí),會(huì)報(bào)錯(cuò)

          ? ? ? ? ?除了上面的不同點(diǎn)之后,@Inject和@Autowired完全等價(jià)。


          版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明。

          本文鏈接:

          https://blog.csdn.net/qq_35634181/article/details/104276056





          粉絲福利:Java從入門(mén)到入土學(xué)習(xí)路線(xiàn)圖

          ???

          ?長(zhǎng)按上方微信二維碼?2 秒


          感謝點(diǎn)贊支持下哈?

          瀏覽 61
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  波多野吉衣网站 | 在线观看免费无码视频 | 日本婬片A片免费免费的 | 夜夜躁狠狠躁日日 | 精品人人妻人人澡人人爽牛牛 |