<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>

          【88期】面試官問:你能說說 Spring 中,接口的bean是如何注入的嗎?

          共 3175字,需瀏覽 7分鐘

           ·

          2020-11-11 04:15

          程序員的成長之路
          互聯(lián)網(wǎng)/程序員/技術(shù)/資料共享?
          關(guān)注

          閱讀本文大概需要 3.5 分鐘。
          來自:cnblogs.com/aland-1415/p/11991170.html

          問:

          這個問題困擾了我好久,一直疑問這個接口的bean是怎么注入進(jìn)去的?因為只看到使用@Service注入了實(shí)現(xiàn)類serviceImpl,使用時怎么能獲取的接口,而且還能調(diào)用到實(shí)現(xiàn)類的方法,難道這個接口是在什么時候自動注入了進(jìn)去,且和實(shí)現(xiàn)類關(guān)聯(lián)上了?
          接口
          public?interface?TestService?{

          ????public?String?test();
          }
          實(shí)現(xiàn)類impl
          @Service
          public?class?TestServiceImpl?implements?TestService{

          ????@Override
          ????public?String?test()?{
          ????????return?"TestServiceImpl";
          ????}
          }
          Controller的調(diào)用:
          @RestController
          public?class?TestCtl?{

          ????@Autowired
          ????private?TestService?testService;

          ????@RequestMapping("/test")
          ????public?String?test()?{
          ????????return?testService.test();
          ????}
          }
          請求結(jié)果:

          答:

          后來才知道,并沒有注入接口的bean,只注入了實(shí)現(xiàn)類serviceImpl的bean,接口只是用來接收的。
          這里就要說到@Autowired/@Resource的注入原理了:@Autowired是Spring的注解,Autowired默認(rèn)先按byType,如果發(fā)現(xiàn)找到多個bean,則,又按照byName方式比對,如果還有多個,則報出異常;@Resource 是JDK1.6支持的注解,默認(rèn)按照名稱(Byname)進(jìn)行裝配, 如果沒有指定name屬性,當(dāng)注解寫在字段上時,默認(rèn)取字段名,按照名稱查找,如果注解寫在setter方法上默認(rèn)取屬性名進(jìn)行裝配。當(dāng)找不到與名稱匹配的bean時才按照類型進(jìn)行裝配。但是需要注意的是,如果name屬性一旦指定,就只會按照名稱進(jìn)行裝配。
          再來說Controller獲取實(shí)例的過程:使用@Autowired,程序在spring的容器中查找類型是TestService的bean,剛好找到有且只有一個此類型的bean,即testServiceImpl,所以就把testServiceImpl自動裝配到了controller的實(shí)例testService中,testService其實(shí)就是TestServiceImpl實(shí)現(xiàn)類;
          如果使用的是@Resource,則是先在容器中查找名字為testService的bean,但并沒有找到,因為容器中的bean名字是TestServiceImpl(如果@Service沒指定bean的value屬性,則注入bean的名字就是類名,如果指定了則是指定的名字),然后再通過類型查找TestService類型的bean,找到唯一的了個TestService類型bean(即TestServiceImpl),所以就自動裝配實(shí)例成功了。更多面試題,歡迎關(guān)注公眾號Java面試題精選

          注:

          byName 通過參數(shù)名 自動裝配,如果一個bean的name 和另外一個bean的 property 相同,就自動裝配。
          byType 通過參數(shù)的數(shù)據(jù)類型自動自動裝配,如果一個bean的數(shù)據(jù)類型和另外一個bean的property屬性的數(shù)據(jù)類型兼容,就自動裝配
          效率上來說@Autowired/@Resource差不多,不過推薦使用@Resource一點(diǎn),因為當(dāng)接口有多個實(shí)現(xiàn)時@Resource直接就能通過name屬性來指定實(shí)現(xiàn)類,而@Autowired還要結(jié)合@Qualifier注解來使用,且@Resource是jdk的注釋,可與Spring解耦。

          問:

          如果一個接口有多個實(shí)現(xiàn)類時,通過注解獲取實(shí)例時怎么知道應(yīng)該獲取的是哪一個實(shí)現(xiàn)類serviceImpl呢?
          再增加了一個實(shí)現(xiàn)類TestServiceImpl2
          @Service
          public?class?TestServiceImpl2?implements?TestService{

          ????@Override
          ????public?String?test()?{
          ????????return?"TestServiceImpl2";
          ????}
          }

          答:

          多個實(shí)現(xiàn)類的話可通過以下2種方式來指定具體要使用哪一個實(shí)現(xiàn):

          1、 通過指定bean的名字來明確到底要實(shí)例哪一個類

          @Autowired 需要結(jié)合@Qualifier來使用,如下:
          ????@Autowired
          ????@Qualifier("testServiceImpl")
          ????private?TestService?testService;
          @Resource可直接通過指定name屬性的值即可,不過也可以使用@Qualifier(有點(diǎn)多此一舉了…)
          ????@Resource(name?=?"testServiceImpl")
          ????private?TestService?testService;????
          @Resource如果不顯示的指定name值,就會自動把實(shí)例變量的名稱作為name的值的,所以也可以直接這樣寫:
            ?@Resource
          ????private?TestService?testServiceImpl;

          2、 通過在實(shí)現(xiàn)類上添加@Primary注解來指定默認(rèn)加載類

          @Service
          @Primary
          public?class?TestServiceImpl2?implements?TestService{

          ????@Override
          ????public?String?test()?{
          ????????return?"TestServiceImpl2";
          ????}
          }
          這樣如果在使用@Autowired/@Resource獲取實(shí)例時如果不指定bean的名字,就會默認(rèn)獲取TestServiceImpl2的bean,如果指定了bean的名字則以指定的為準(zhǔn)。

          問:

          為什么非要調(diào)用接口來多此一舉,而不直接調(diào)用實(shí)現(xiàn)類serviceImpl的bean來得簡單明了呢?

          答:

          1、 直接獲取實(shí)現(xiàn)類serviceImpl的bean也是可以的;
          2、 至于加一層接口的原因:一是AOP程序設(shè)置思想指導(dǎo),給別人調(diào)用的接口,調(diào)用者只想知道方法和功能,而對于這個方法內(nèi)部邏輯怎么實(shí)現(xiàn)的并不關(guān)心;二是可以降低各個模塊間的關(guān)聯(lián),實(shí)現(xiàn)松耦合、程序分層、高擴(kuò)展性,使程序更加靈活,他除了在規(guī)范上有卓越貢獻(xiàn)外,最精髓的是在多態(tài)上的運(yùn)用;繼承只能單一繼承,接口卻可以多實(shí)現(xiàn)
          3、 當(dāng)業(yè)務(wù)邏輯簡單,變更較少,項目自用時,省略掉接口直接使用實(shí)現(xiàn)類更簡單明了;反之則推薦使用接口;

          推薦閱讀:

          【87期】面試官問:Java序列化和反序列化為什么要實(shí)現(xiàn)Serializable接口

          【86期】五個刁鉆的String面試問題及解答

          【85期】談?wù)凧ava面向?qū)ο笤O(shè)計的六大原則,中高級面試常問!

          5T技術(shù)資源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,單片機(jī),樹莓派,等等。在公眾號內(nèi)回復(fù)「2048」,即可免費(fèi)獲?。?!

          微信掃描二維碼,關(guān)注我的公眾號

          朕已閱?

          瀏覽 64
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  性猛交XXXX乱大交孕妇 | 伊人青青在线播放 | 天天艹夜夜艹 | 天堂网在线视频免费观看 | 黄色视频操逼 |