spring中@autowired、@Qualifier、@Primary注解的使用說明
@autowired、@Qualifier、@Primary注解的使用
學(xué)過spring的朋友應(yīng)該都知道@Autowired注解,將IOC容器中的屬性注入到當前屬性中。
一:當前屬性不是必須的時
@Autowired注解有且只有這一個屬性
@Autowired(required = false)
二:容器中存在多個同種類型的組建
1:通過指定屬性的名字與容器中組建id相同選擇注入的組建
2:通過@Qualifier注解選擇注入組建的id
@Qualifier("bookDao2")
@Autowired(required = false)
private BookDao bookDao;
3:通過@Primary注解在注入組建時指定使用組建主要選擇哪一個,注入時將優(yōu)先選擇帶有@Primary注解的組建。
當同時使用@Qualifier注解和@Primary注解時,當然優(yōu)先使用@Qualifier注解指定的組建
@Primary
@Bean(name = "bookDao2")
public BookDao bookDao(){
BookDao bookDao = new BookDao();
bookDao.setLable(2);
return bookDao;
}
@Autowired @Resource @Qualifier @Primary的區(qū)別
@Autowired @Resource @Qualifier的區(qū)別
實用理解:@Autowired @Resource 二選其一,看中哪個就用哪個。
簡單理解:
@Autowired根據(jù)類型注入,@Resource默認根據(jù)名字注入,其次按照類型搜索@Autowired@Qualifie(“userService”)兩個結(jié)合起來可以根據(jù)名字和類型注入
復(fù)雜理解:
比如你有這么一個Bean
@Service(“UserService”) public Class UserServiceImpl implements UserService{}; 現(xiàn)在你想在UserController 里面使用這個UserServiceImpl public Class UserController {
@AutoWire//當使用這個注入的時候上面的 UserServiceImpl 只需要這樣寫 @Service,這樣就會自動找到UserService這個類型以及他的子類型。UserServiceImpl 實現(xiàn)了UserService,所以能夠找到它。不過這樣有一個缺點,就是當UserService實現(xiàn)類有兩個以上的時候,這個時候會找哪一個呢,這就造成了沖突,所以要用@AutoWire注入的時候要確保UserService只有一個實現(xiàn)類。@Resource默認情況下是按照名稱進行匹配,如果沒有找到相同名稱的Bean,則會按照類型進行匹配,有人可能會想了,這下好了,用這個是萬能的了,不用管名字了,也不用管類型了,但這里還是有缺點。首先,根據(jù)這個注解的匹配效果可以看出,它進行了兩次匹配,也就是說,如果你在UserService這個類上面這樣寫注解,@Service,它會怎么找呢,首先是找相同名字的,如果沒有找到,再找相同類型的,而這里的@Service沒有寫名字,這個時候就進行了兩次搜索,顯然,速度就下降了許多。也許你還會問,這里的@Service本來就沒有名字,肯定是直接進行類型搜索啊。其實不是這樣的,UserServiceImpl 上面如果有@Service默認的名字 是這個userServiceImpl,注意看,就是把類名前面的大寫變成小寫,就是默認的Bean的名字了。 @Resource根據(jù)名字搜索是這樣寫@Resource(“userService”),如果你寫了這個名字叫userService,那么UserServiceImpl上面必須也是這個名字,不然還是會報錯。@Autowired@Qualifie(“userService”)是直接按照名字進行搜索,也就是說,對于UserServiceImpl 上面@Service注解必須寫名字,不寫就會報錯,而且名字必須是@Autowired @Qualifie(“userService”) 保持一致。如果@Service上面寫了名字,而@Autowired @Qualifie() ,一樣會報錯。
private UserService userService; }
說了這么多,可能你有些說暈了,那么怎么用這三個呢,要實際的工作是根據(jù)實際情況來使用的,通常使用AutoWire和@Resource多一些,bean的名字不用寫,而UserServiceImpl上面能會這樣寫 @Service(“userService”)。這里的實際工作情況,到底是什么情況呢?說白了就是整個項目設(shè)計時候考慮的情況,如果你的架構(gòu)設(shè)計師考慮的比較精細,要求比較嚴格,要求項目上線后的訪問速度比較好,通常是考慮速度了。這個時候@AutoWire沒有@Resource好用,因為@Resource可以根據(jù)名字來搜索,是這樣寫的@Resource(“userService”)。這個@Autowired @Qualifie(“userService”) 也可以用名字啊,為什么不用呢,原因很簡單,這個有點長,不喜歡,增加工作量。因為根據(jù)名字搜索是最快的,就好像查數(shù)據(jù)庫一樣,根據(jù)Id查找最快。因為這里的名字與數(shù)據(jù)庫里面的ID是一樣的作用。這個時候,就要求你多寫幾個名字,工作量自然就增加了。而如果你不用注解,用xml文件的時候,對于注入Bean的時候要求寫一個Id,xml文件時候的id就相當于這里的名字。
說了那么多沒用,你能做的就是簡單直接,什么最方便就用什么,
你就直接用@Resource得了,如果你喜歡用@AutoWire也行,不用寫名字。
通常情況一個Bean的注解寫錯了,會報下面這些錯誤,最為常見,
No bean named ‘user' is defined,這個表示沒有找到被命名為user的Bean,通俗的說,就是名字為user的類型,以及它的子類型,出現(xiàn)這個錯誤的原因就是注入時候的類型名字為user,而搜索的時候找不到,也就是說可能那個搜索的類型,并沒有命令為user,解決辦法就是找到這個類型,去命令為user,
下面這個錯誤也常見,
No qualifying bean of type [com.service.UserService] found for dependency:
這個錯誤的原因就是類型上面沒有加@Service這個注入,不僅僅是@Service,如果是其他層也會出現(xiàn)這個錯誤,這里我是以Service為例子說明,如果是DAO層就是沒有加@Repository,Controller層,則是沒有加@Controller。
還有,如果你還是想再簡單點,無論是DAO,Controller,Service三個層,都可以用這個注解,@Component,這個注解通用所有的Bean,這個時候你可能會說了,有通常的為什么用的人少呢,那是因為MVC這個分層的設(shè)計原則,用@Repository,@Service,@Controller,這個可以區(qū)別MVC原則中的DAO,Service,Controller。便于識別。
@Qualifier VS @Primary
還有另一個名為 @Primary 的注解,我們也可以用來發(fā)生依賴注入的歧義時決定要注入哪個 bean。當存在多個相同類型的 bean 時,此注解定義了首選項。除非另有說明,否則將使用與 @Primary 注釋關(guān)聯(lián)的 bean 。
我們來看一個例子:
@Bean
public Employee tomEmployee() {
return new Employee("Tom");
}
@Bean
@Primary
public Employee johnEmployee() {
return new Employee("john");
}
在此示例中,兩個方法都返回相同的 Employee類型。Spring 將注入的 bean 是方法 johnEmployee 返回的 bean。這是因為它包含 @Primary 注解。當我們想要指定默認情況下應(yīng)該注入特定類型的 bean 時,此注解很有用。
如果我們在某個注入點需要另一個 bean,我們需要專門指出它。我們可以通過 @Qualifier 注解來做到這一點。例如,我們可以通過使用 @Qualifier 注釋來指定我們想要使用 tomEmployee 方法返回的 bean 。
值得注意的是,如果 @Qualifier 和 @Primary 注釋都存在,那么 @Qualifier 注釋將具有優(yōu)先權(quán)。基本上,@Primary 是定義了默認值,而 @Qualifier 則非常具體。
當然@Component 也可以使用@Primary 注解,這次使用的還是上面的示例:
@Component
@Primary
public class FooFormatter implements Formatter {
public String format() {
return "foo";
}
}
@Component
public class BarFormatter implements Formatter {
public String format() {
return "bar";
}
}
在這種情況下,@Primary 注解指定了默認注入的是 FooFormatter,消除了場景中的注入歧義。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Mybatis多表關(guān)聯(lián)查詢的實現(xiàn)(DEMO)
本節(jié)要實現(xiàn)的是多表關(guān)聯(lián)查詢的簡單demo。場景是根據(jù)id查詢某商品分類信息,并展示該分類下的商品列表,需要的朋友可以參考下2017-02-02
Java調(diào)用DeepSeek?API的最佳實踐及詳細代碼示例
這篇文章主要介紹了如何使用Java調(diào)用DeepSeek?API,包括獲取API密鑰、添加HTTP客戶端依賴、創(chuàng)建HTTP請求、處理響應(yīng)、錯誤處理、測試和部署,文章還提供了代碼示例和注意事項,幫助開發(fā)者順利完成API調(diào)用,需要的朋友可以參考下2025-02-02
SpringBoot項目中同時操作多個數(shù)據(jù)庫的實現(xiàn)方法
在實際項目開發(fā)中可能存在需要同時操作兩個數(shù)據(jù)庫的場景,本文主要介紹了SpringBoot項目中同時操作多個數(shù)據(jù)庫的實現(xiàn)方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03
Java 實現(xiàn)網(wǎng)絡(luò)爬蟲框架詳細代碼
這篇文章主要介紹了Java 實現(xiàn)網(wǎng)絡(luò)爬蟲框架,主要是用于爬取網(wǎng)絡(luò)上一些內(nèi)容,比如超鏈接之類的,需要的朋友可以參考下面文章內(nèi)容2021-09-09

