Spring中接口的bean是如何注入的


大家都知道@Service注入的是實現類serviceImpl,那使用時怎么能獲取到接口,而且還能調用到實現類的方法。

  接口:

public interface TestService{    
    public String test();     
}

   實現類:

@Service
public class TestServiceImpl implements TestService{


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

  Controller類:

@RestController
public class TestController{

   @Autowired  
   private TestService testService;

   @RequestMapping("/test")
   public String test(){
        return testService.test();
    }

}

  請求結果:

 

 

 

其中只注入了實現類serviceImpl的bean,接口只是用來接收的。這里就要說到@Autowired/@Resource的注入原理:@Autowired是Spring的注解,Autowired默認先按byType,如果發現找到多個bean,則再按照byName方式比對,如果還有多個bean,則報錯Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException;@Resource是JDK1.6支持的注解,默認按照byName進行裝配。如果沒有指定name屬性,當注解寫在字段上時,默認取字段名按名稱查找,當注解寫在setter方法上默認取屬性名,當找不到與名稱匹配的bean時才按照類型匹配。

再來說Controller獲取實例的過程:使用@Autowired,程序在spring的容器中查找類型時TestService的bean,剛好找到有且只有一個此類型的bean,即TestServiceImpl,所以就把testServiceImpl自動裝配到了Controller的實例TestService中。

問:如果一個接口有多個實現類時,通過注解獲取實例時怎么知道應該獲取的是哪一個實現類serviceImpl呢?

  增加一個新的實現類:

@Service
public class TestServiceImpl2 implements TestService{
    @Override
    public String test() {
        return "TestServiceImpl2";
    }

}

1.通過指定bean的名稱來明確到底要實例哪一個類

@Autowired需要結合@Qualifier,注:實現類的開頭小寫類名TestServiceImpl2->testServiceImpl2

        @Autowired
        @Qualifier("testServiceImpl2")
        private TestService testService;     

@Resource也可以使用(name="testServiceImpl2"),如果不顯示的指定name值,就會自動把實例變量的名稱作為name的值

      @Resource
      private TestService testServiceImpl2;

2.通過在實現類上添加@Primary注解來指定默認加載類,如果任然指定了bean的名字則以指定的為准

@Service
@Primary
public class TestServiceImpl2 implements TestService{
    @Override
    public String test() {
        return "TestServiceImpl2";
    }

}

問:為什么非要調用接口來多此一舉,而不直接調用實現類serviceImpl的bean來得簡單明了呢?

直接使用serviceImpl的bean是可以的,這樣加一層接口的原因:1.AOP程序的思想,給別人調用的接口,調用這只想知道方法和功能,而對於這個方法內部邏輯實現並不關心。2.降低各個模塊間的關聯,實現松耦合、程序分成、最主要的體現了繼承只能單繼承,接口卻可以多實現

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM