最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring BeanName 的自動生成原理示例詳解

 更新時間:2023年09月18日 09:55:41   作者:泠青沼~  
這篇文章主要介紹了Spring BeanName 的自動生成原理示例詳解,本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

?? 一、默認 name 生成原理

在 Spring 中,提供了 BeanNameGenerator 用來生成 BeanName:

public interface BeanNameGenerator {
	/**
	 * Generate a bean name for the given bean definition.
	 * @param definition the bean definition to generate a name for
	 * @param registry the bean definition registry that the given definition
	 * is supposed to be registered with
	 * @return the generated bean name
	 */
	String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry);
}

在這里插入圖片描述

  • DefaultBeanNameGenerator:XML 配置中,默認的 BeanName 就是在這個中自動生成的
  • AnnotationBeanNameGenerator:Java 配置中,如果使用了 @Component 等注解標記的 Bean,沒有設(shè)置默認的名稱,則通過這個來生成默認的 BeanName
public class DefaultBeanNameGenerator implements BeanNameGenerator {
	/**
	 * A convenient constant for a default {@code DefaultBeanNameGenerator} instance,
	 * as used for {@link AbstractBeanDefinitionReader} setup.
	 * @since 5.2
	 */
	public static final DefaultBeanNameGenerator INSTANCE = new DefaultBeanNameGenerator();
	@Override
	public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
		return BeanDefinitionReaderUtils.generateBeanName(definition, registry);
	}
}

可以看到,generateBeanName 這個方法實際上代理了 BeanDefinitionReaderUtils.generateBeanName 方法的執(zhí)行,真正的 BeanName 的生成是在這個方法中完成的

在這里插入圖片描述

public static String generateBeanName(
		BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean)
		throws BeanDefinitionStoreException {
    // 這里就是獲取到 XML 中 bean 標簽里邊配置的 class 屬性的值
	String generatedBeanName = definition.getBeanClassName();
    // 判斷是否有 class 這個屬性值,如果沒有的話,則在 parnetName 存在的情況下,
    // 使用 parentName+$child 來作為 生成的 beanName
	if (generatedBeanName == null) {
		if (definition.getParentName() != null) {
			generatedBeanName = definition.getParentName() + "$child";
		}
        // 如果沒有 parentName,則嘗試使用 factoryBeanName
		else if (definition.getFactoryBeanName() != null) {
			generatedBeanName = definition.getFactoryBeanName() + "$created";
		}
	}
    // 如果經(jīng)過上面的處理,還是沒有 generatedBeanName,那么就要拋異常了
	if (!StringUtils.hasText(generatedBeanName)) {
		throw new BeanDefinitionStoreException("Unnamed bean definition specifies neither " +
				"'class' nor 'parent' nor 'factory-bean' - can't generate bean name");
	}
	if (isInnerBean) {
		// Inner bean: generate identity hashcode suffix.
		return generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(definition);
	}
	// Top-level bean: use plain class name with unique suffix if necessary.
    // 我們的默認 BeanName,實際上是在這個方法中生成的
	return uniqueBeanName(generatedBeanName, registry);
}
public static String uniqueBeanName(String beanName, BeanDefinitionRegistry registry) {
	String id = beanName;
	int counter = -1;
	// Increase counter until the id is unique.
    //GENERATED_BEAN_NAME_SEPARATOR 實際上就是 #
    // 所有這里是把類的全路徑和 # 拼在一起
	String prefix = beanName + GENERATED_BEAN_NAME_SEPARATOR;
    // 后面的判斷表示這個 id 是否已經(jīng)被注冊了,如果已經(jīng)被注冊,則繼續(xù)生成新的 id
	while (counter == -1 || registry.containsBeanDefinition(id)) {
		counter++;
		id = prefix + counter;
	}
    //最終生成的 id 就是 org.javaboy.bean.User#0
	return id;
}

由此可以看到,默認的 BeanName 就是類的全路徑+ # +序列號,如 com.dong.Cat#0 、 com.dong.Cat#1 。對于序列號為 0 的 BeanName,還有一個默認的名稱,就是類的全路徑,不加任何序列號上面這個生成 BeanName 的方法是在 BeanDefinitionParserDelegate#parseBeanDefinitionElement 方法中執(zhí)行的,具體的邏輯如下:

if (beanDefinition != null) {
    // 當前沒有配置 BeanName,即 bean 標簽中沒有 id 或者 name 屬性
	if (!StringUtils.hasText(beanName)) {
		try {
			if (containingBean != null) {
				beanName = BeanDefinitionReaderUtils.generateBeanName(
						beanDefinition, this.readerContext.getRegistry(), true);
			}
			else {
                //這個地方,最終會調(diào)用到上面的邏輯去生成 BeanName
                //com.dong.Cat#0
				beanName = this.readerContext.generateBeanName(beanDefinition);
				// Register an alias for the plain bean class name, if still possible,
				// if the generator returned the class name plus a suffix.
				// This is expected for Spring 1.2/2.0 backwards compatibility.
                // 獲取一個類的全路徑 com.dong.Cat
                //!this.readerContext.getRegistry().isBeanNameInUse(beanClassName) 表示 beanClassName 還沒有作為一個 BeanName 注冊到 Spring 容器中
				String beanClassName = beanDefinition.getBeanClassName();
				if (beanClassName != null &&
						beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
						!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
					//將之添加別名中,相當于類的全路徑本身,成為了 Bean 的一個別名
                    aliases.add(beanClassName);
				}
			}
			if (logger.isTraceEnabled()) {
				logger.trace("Neither XML 'id' nor 'name' specified - " +
						"using generated bean name [" + beanName + "]");
			}
		}
		catch (Exception ex) {
			error(ex.getMessage(), ele);
			return null;
		}
	}
	String[] aliasesArray = StringUtils.toStringArray(aliases);
	return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}

這就是為什么默認生成的 BeanName 中,#0可有可無的原因

?? 二、id 和 name 屬性處理原理

id 和 name 屬性的處理其實也是在 BeanDefinitionParserDelegate#parseBeanDefinitionElement 方法中:

// 獲取 bean 標簽中的 id 屬性值,user
String id = ele.getAttribute(ID_ATTRIBUTE);
// 獲取 bean 標簽中 name 屬性值,user;user2;user3
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
    //MULTI_VALUE_ATTRIBUTE_DELIMITERS 變量實際上就是 ;,空格
    // 所以這個方法實際上就是根據(jù) ; , 以及 空格 去拆分 nameAttr,將之拆分為一個數(shù)組
	String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
	// name 拆出來的屬性將作為這個 bean 的別名
    aliases.addAll(Arrays.asList(nameArr));
}
//使用 id 作為 beanName
String beanName = id;
//這里相當于判斷這個 bean 標簽沒有 id 屬性,但是有 name 屬性
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
    //將 name 拆出來的集合中的第一項作為 beanName
	beanName = aliases.remove(0);
	if (logger.isTraceEnabled()) {
		logger.trace("No XML 'id' specified - using '" + beanName +
				"' as bean name and " + aliases + " as aliases");
	}
}

但是,經(jīng)過上面的處理,beanName 還是有可能為空。如果還為空,則進入到上面的邏輯中,自動生成 BeanName

到此這篇關(guān)于Spring BeanName 的自動生成原理的文章就介紹到這了,更多相關(guān)Spring BeanName自動生成原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot中數(shù)據(jù)傳輸對象(DTO)的實現(xiàn)

    SpringBoot中數(shù)據(jù)傳輸對象(DTO)的實現(xiàn)

    本文主要介紹了SpringBoot中數(shù)據(jù)傳輸對象(DTO)的實現(xiàn),包括了手動創(chuàng)建DTO、使用ModelMapper和Lombok創(chuàng)建DTO的示例,具有一定的參考價值,感興趣的可以了解一下
    2024-07-07
  • Java數(shù)據(jù)結(jié)構(gòu)實現(xiàn)折半查找的算法過程解析

    Java數(shù)據(jù)結(jié)構(gòu)實現(xiàn)折半查找的算法過程解析

    這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)實現(xiàn)折半查找的算法過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03
  • Java多線程中的CountDownLatch詳細解讀

    Java多線程中的CountDownLatch詳細解讀

    這篇文章主要介紹了Java多線程中的CountDownLatch詳細解讀,一個同步輔助類,在完成一組正在其他線程中執(zhí)行的操作之前,它允許一個或多個線程一直等待,用給定的計數(shù) 初始化 CountDownLatch,需要的朋友可以參考下
    2023-11-11
  • java虛擬機中多線程總結(jié)

    java虛擬機中多線程總結(jié)

    在本篇內(nèi)容中小編給大家分享的是關(guān)于java虛擬機中多線程的知識點總結(jié)內(nèi)容,需要的朋友們參考學(xué)習(xí)下。
    2019-06-06
  • Java Spring框架簡介與Spring IOC詳解

    Java Spring框架簡介與Spring IOC詳解

    Spring 框架是一個輕量級的解決方案,可以一站式地構(gòu)建企業(yè)級應(yīng)用。它是為了解決 企業(yè)應(yīng)用開發(fā)的復(fù)雜性而創(chuàng)建的。Spring 使用基本的 JavaBean 來完成以前只可能由 EJB 完成的事情。IOC 是 Inversion of Control 的縮寫,多數(shù)書籍翻譯成控制反轉(zhuǎn)
    2021-09-09
  • java 泛型的詳解及實例

    java 泛型的詳解及實例

    這篇文章主要介紹了java 泛型的詳解及實例的相關(guān)資料,希望通過本文大家能徹底掌握泛型的使用方法,需要的朋友可以參考下
    2017-08-08
  • 詳解Java集合中的基本數(shù)據(jù)結(jié)構(gòu)

    詳解Java集合中的基本數(shù)據(jù)結(jié)構(gòu)

    總有小伙伴讓我總結(jié)一下Java集合中的基本數(shù)據(jù)結(jié)構(gòu)的相關(guān)知識,今天特地整理了本篇文章,文中有非常詳細的介紹,需要的朋友可以參考下
    2021-06-06
  • Spring中的@Conditional注解使用和原理詳解

    Spring中的@Conditional注解使用和原理詳解

    這篇文章主要介紹了Spring中的@Conditional注解使用和原理詳解,@Conditional在Spring4.0中被引入,用于開發(fā)"If-Then-Else"類型的bean注冊條件檢查,在@Conditional之前,也有一個注解@Porfile起到類似的作用,需要的朋友可以參考下
    2024-01-01
  • Java位運算和邏輯運算的區(qū)別實例

    Java位運算和邏輯運算的區(qū)別實例

    Java位運算和邏輯運算的區(qū)別實例,請參考下面代碼,希望對你有所幫助
    2013-02-02
  • 解決IDEA使用maven創(chuàng)建Web項目,出現(xiàn)500錯誤的問題

    解決IDEA使用maven創(chuàng)建Web項目,出現(xiàn)500錯誤的問題

    本文主要介紹了在使用Maven創(chuàng)建項目并導(dǎo)入依賴寫完測試代碼后運行出現(xiàn)500錯誤的解決步驟,這種問題的根本原因是Tomcat啟動后缺少某些支持的jar包,導(dǎo)致運行出錯,解決方法是在項目結(jié)構(gòu)中找到Artifacts,點擊要編輯的項目
    2024-10-10

最新評論

密云县| 永德县| 松滋市| 兰考县| 海南省| 天台县| 德昌县| 兴安盟| 武邑县| 盘锦市| 新民市| 柯坪县| 汉沽区| 盐津县| 永寿县| 南城县| 大同市| 石门县| 富锦市| 梨树县| 正定县| 望都县| 吉林市| 丘北县| 嘉义市| 南通市| 聂拉木县| 洪雅县| 得荣县| 景泰县| 金湖县| 新野县| 昌邑市| 七台河市| 江津市| 板桥市| 甘南县| 南木林县| 夹江县| 文水县| 河西区|