詳解Spring的autowire-candidate設(shè)計(jì)
Xml配置文件中的default-autowire-candidates屬性
有的同學(xué)對(duì)這個(gè)配置可能不熟悉或者說都不知道這個(gè)配置的存在,那首先我們看下default-autowire-candidates這個(gè)配置是放在何處的:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd default-autowire-candidates="service*"> <bean id="serviceA" class="org.wonder.frame.xmlConfig.SetterBean$ServiceA" autowire-candidate="false"/> <bean id="serviceB" class="org.wonder.frame.xmlConfig.SetterBean$ServiceB" /> <bean id="setterBean" class="org.wonder.frame.xmlConfig.SetterBean" autowire="byType" /> </beans>
在idea中我們可以點(diǎn)開 default-autowire-candidates這個(gè)屬性所在的spring-beans.xsd就能看到官方對(duì)這個(gè)屬性的注釋:
A default bean name pattern for identifying autowire candidates: e.g. "Service", "data", "Service", "dataService". Also accepts a comma-separated list of patterns: e.g. "Service,*Dao". See the documentation for the 'autowire-candidate' attribute of the 'bean' element for the semantic details of autowire candidate beans.
簡(jiǎn)單翻譯下也就是說這個(gè)屬性可以標(biāo)示配置文件中的所有Bean默認(rèn)能否成為自動(dòng)注入候選者的名稱匹配模式,比如 "Service", "data", "Service", "dataService".也支持以逗號(hào)分隔的字符串模式列表:"Service,Dao". 比如上面配置文件中配置的service\就匹配了serviceA,serviceB兩個(gè)Bean.但是Spring的設(shè)計(jì)規(guī)定serviceA自身配置的autowire-candidate為false會(huì)覆蓋default-autowire-candidates配置,所以serviceA是不會(huì)成為自動(dòng)注入的候選者。
匹配邏輯算法
我們深入到源碼中看下Spring是如何根據(jù)這個(gè)匹配模式來與自身bean名稱來匹配的
String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE); if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) { String candidatePattern = this.defaults.getAutowireCandidates(); if (candidatePattern != null) { String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern); bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName)); } } else { bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate)); }
很清楚,在bean本身配置autowire-candidate為空或者默認(rèn)的情況下,Spring會(huì)把default-autowire-candidates字符串轉(zhuǎn)換成數(shù)組,然后依賴PatternMatchUtils類的simpleMatch方法來驗(yàn)證當(dāng)前bean的名稱是否匹配,成功與否都會(huì)賦值給當(dāng)前bean的autowireCandidate屬性。其實(shí)最主要的還是PatternMatchUtils.simpleMatch方法
PatternMatchUtils.simpleMatch
public static boolean simpleMatch(@Nullable String pattern, @Nullable String str) { //pattern 匹配模式為空 或者待匹配字符串為空就返回false if (pattern == null || str == null) { return false; } //找到第一個(gè)* 在匹配模式字符串中的的索引 int firstIndex = pattern.indexOf('*'); if (firstIndex == -1) { //索引為空的情況下就代表 模式字符串要和待匹配字符串相等。 return pattern.equals(str); } //*在第一位 if (firstIndex == 0) { //*在第一位 且匹配模式字符串長(zhǎng)度為1 那就直接返回true ,比如 * if (pattern.length() == 1) { return true; } //找到下一個(gè)*的起始位置 int nextIndex = pattern.indexOf('*', firstIndex + 1); if (nextIndex == -1) { //如果沒有*了,就判斷 待匹配的字符串是否是以pattern結(jié)尾的。 //比如*service Aservice就滿足這種情況 return str.endsWith(pattern.substring(1)); } //截取第一個(gè)* 和之后一個(gè)* 之間的字符串 String part = pattern.substring(1, nextIndex); if (part.isEmpty()) { return simpleMatch(pattern.substring(nextIndex), str); } //str 是指待匹配的字符 int partIndex = str.indexOf(part); while (partIndex != -1) { if (simpleMatch(pattern.substring(nextIndex), str.substring(partIndex + part.length()))) { return true; } //從partIndex+1 開始計(jì)算part的索引 partIndex = str.indexOf(part, partIndex + 1); } return false; } //待匹配字符串的長(zhǎng)度比 第一個(gè)*的索引 大或者相等的情況下 //截取模式字符串 0 到 第一個(gè)*號(hào)之間的字符串 ,截取 待匹配字符串 0 到 第一個(gè)*號(hào)之間的字符串 對(duì)比 //如果相等 ,再截取 模式字符串 第一個(gè)*號(hào)之后的字符串 和 待匹配 字符串 第一個(gè)*號(hào)之后的字符串 去做匹配 return (str.length() >= firstIndex && pattern.substring(0, firstIndex).equals(str.substring(0, firstIndex)) && simpleMatch(pattern.substring(firstIndex), str.substring(firstIndex))); }
這個(gè)Utils類的工具函數(shù)實(shí)現(xiàn)的字符串模糊匹配算法在我們?nèi)粘i_發(fā)中對(duì)字符串的操作方面也會(huì)有或多或少的幫助。
總結(jié)
Spring中的很多設(shè)計(jì)細(xì)節(jié)總是給我們很多驚喜,從中我們也可以很多小技巧,給我們?nèi)粘i_發(fā)會(huì)帶來不少啟發(fā)。
以上就是詳解Spring的autowire-candidate設(shè)計(jì)的詳細(xì)內(nèi)容,更多關(guān)于Spring的autowire-candidate設(shè)計(jì)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot2.X Devtools熱部署實(shí)現(xiàn)解析
這篇文章主要介紹了SpringBoot2.X Devtools熱部署實(shí)現(xiàn)解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08SpringMVC框架實(shí)現(xiàn)圖片上傳與下載
這篇文章主要為大家詳細(xì)介紹了SpringMVC框架實(shí)現(xiàn)圖片上傳與下載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08詳解Lombok安裝及Spring Boot集成Lombok
這篇文章主要介紹了詳解Lombok安裝及Spring Boot集成Lombok,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-03-03SpringBoot MyBatis簡(jiǎn)單快速入門例子
MyBatis 是一款優(yōu)秀的持久層框架,它支持自定義 SQL、存儲(chǔ)過程以及高級(jí)映射。這篇文章主要介紹了SpringBoot MyBatis快速入門-簡(jiǎn)單例子,需要的朋友可以參考下2021-07-07Java解除文件占用即Dom4j操作后實(shí)現(xiàn)xml關(guān)流
這篇文章主要介紹了Java解除文件占用即Dom4j操作后實(shí)現(xiàn)xml關(guān)流,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04java 中mongodb的各種操作查詢的實(shí)例詳解
這篇文章主要介紹了java 中mongodb的各種操作查詢的實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下2017-09-09idea中Maven鏡像源詳細(xì)配置步驟記錄(對(duì)所有項(xiàng)目)
Maven是一個(gè)能使我們的java程序開發(fā)節(jié)省時(shí)間和精力,是開發(fā)變得相對(duì)簡(jiǎn)單,還能使開發(fā)規(guī)范化的工具,下面這篇文章主要給大家介紹了關(guān)于idea中Maven鏡像源詳細(xì)配置(對(duì)所有項(xiàng)目)的相關(guān)資料,需要的朋友可以參考下2023-05-05seata-1.4.0安裝及在springcloud中使用詳解
這篇文章主要介紹了seata-1.4.0安裝及在springcloud中使用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12Spring框架基于AOP實(shí)現(xiàn)簡(jiǎn)單日志管理步驟解析
這篇文章主要介紹了Spring框架基于AOP實(shí)現(xiàn)簡(jiǎn)單日志管理步驟解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06