Springboot注解,Spring源碼入門——DefaultBeanNameGenerator解析

 2023-10-15 阅读 27 评论 0

摘要:  我們知道在spring中每個bean都要有一個id或者name標示每個唯一的bean,在xml中定義一個bean可以指定其id和name值,但那些沒有指定的,或者注解的spring的beanname怎么來的的?就是BeanNameGenerator接口實現的特性。   <bean id="t

  我們知道在spring中每個bean都要有一個id或者name標示每個唯一的bean,在xml中定義一個bean可以指定其id和name值,但那些沒有指定的,或者注解的spring的beanname怎么來的的?就是BeanNameGenerator接口實現的特性。

  <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"><property name="entityManagerFactory" ref="entityManagerFactory" /></bean>

Springboot注解、  BeanNameGenerator接口位于 org.springframework.beans.factory.support 包下面,只聲明了一個方法,接受兩個參數:definition 被生成名字的BeanDefinition實例;registry 生成名字后注冊進的BeanDefinitionRegistry。

    /*** Generate a bean name for the given bean definition.* 根據給定的bean definition 生成一個bean的名字* @param definition the bean definition to generate a name for* @param 參數 definition 需要生成bean name的BeanDefinition實例* @param registry the bean definition registry that the given definition* is supposed to be registered with* @param 參數registry 是 definition 注冊* @return the generated bean name* @return 返回生成的bean name*/String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry);

?  BeanNameGenerator有兩個實現版本,DefaultBeanNameGenerator和AnnotationBeanNameGenerator。其中DefaultBeanNameGenerator是給資源文件加載bean時使用(BeanDefinitionReader中使用);AnnotationBeanNameGenerator是為了處理注解生成bean name的情況。

  DefaultBeanNameGenerator類將具體的處理方式委托給了,BeanDefinitionReaderUtils#generateBeanName(BeanDefinition, BeanDefinitionRegistry)方法處理。  

    /*** Generate a bean name for the given top-level bean definition,    * unique within the given bean factory.* @param beanDefinition the bean definition to generate a bean name for* @param registry the bean factory that the definition is going to be* registered with (to check for existing bean names)* @return the generated bean name* @throws BeanDefinitionStoreException if no unique name can be generated* for the given bean definition*/public static String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {return generateBeanName(beanDefinition, registry, false);}

  這個方法也沒有做任何處理,直接委托了給了generateBeanName(BeanDefinition , BeanDefinitionRegistry , boolean )方法,多指定了一個boolean型參數,是為了區分內部bean(innerBean)和頂級bean(top-level bean).

/*** Generate a bean name for the given bean definition, unique within the* given bean factory.* @param definition the bean definition to generate a bean name for* @param registry the bean factory that the definition is going to be* registered with (to check for existing bean names)* @param isInnerBean whether the given bean definition will be registered* as inner bean or as top-level bean (allowing for special name generation* for inner beans versus top-level beans)    * @param isInnerBean  參數definition會被注冊為一個內部bean還是一個頂級bean(內部bean和頂級bean 都允許使用特殊名字定義)* @return the generated bean name* @throws BeanDefinitionStoreException if no unique name can be generated* for the given bean definition* @throws BeanDefinitionStoreException 當沒有唯一的名稱可供生成的時候拋出異常*/public static String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean)throws BeanDefinitionStoreException {//generatedBeanName定義為類前綴, 讀取bean的className,不一定是運行時的實際類型。String generatedBeanName = definition.getBeanClassName();if (generatedBeanName == null) {//如果類名稱為空,那讀取bean的parent bean name if (definition.getParentName() != null) {generatedBeanName = definition.getParentName() + "$child";}//否則,讀取生成該bean的factoryBean name名稱做前綴。else if (definition.getFactoryBeanName() != null) {generatedBeanName = definition.getFactoryBeanName() + "$created";}}//generatedBeanName為空字符串,拋出異常if (!StringUtils.hasText(generatedBeanName)) {throw new BeanDefinitionStoreException("Unnamed bean definition specifies neither " +"'class' nor 'parent' nor 'factory-bean' - can't generate bean name");}String id = generatedBeanName;//當為內部bean時,調用系統底層的object唯一標識碼生成if (isInnerBean) {// Inner bean: generate identity hashcode suffix. id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(definition);}//否則即為頂級bean,生成策略是前綴+循環數字,直到找到對應自增idelse {// Top-level bean: use plain class name.// Increase counter until the id is unique.int counter = -1;while (counter == -1 || registry.containsBeanDefinition(id)) {counter++;id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + counter;}}return id;}

  關于每個對象的hash code的生成方式,這里面不確定是否和對象重寫的hashCode()方法有關,需要jvm相關資料說明。

//    ObjectUtils.java/*** Return a hex String form of an object's identity hash code.* 返回一個十六進制數從hash code中獲得* @param obj*            the object* @return the object's identity code in hex notation*/public static String getIdentityHexString(Object obj) {return Integer.toHexString(System.identityHashCode(obj));}//    System.java/*** Returns the same hash code for the given object as would be returned by* the default method hashCode(), whether or not the given object's class* overrides hashCode(). The hash code for the null reference is zero.* * @param x*            object for which the hashCode is to be calculated* @return the hashCode* @since JDK1.1*///native 表示操作系統實現的底層框架,用于生成對象的hashcode。jvm的實現還沒有關心。public static native int identityHashCode(Object x);//  Integer.java/*** All possible chars for representing a number as a String*/final static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8','9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l','m', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y','z' };public static String toHexString(int i) {return toUnsignedString(i, 4);}private static String toUnsignedString(int i, int shift) {char[] buf = new char[32];int charPos = 32;int radix = 1 << shift;int mask = radix - 1;do {buf[--charPos] = digits[i & mask];i >>>= shift;} while (i != 0);return new String(buf, charPos, (32 - charPos));}

  重新整理下流程:生成流程分為前后兩部分,前面生成的叫前綴,后面生成的叫后綴。

    1,讀取待生成name實例的類名稱,未必是運行時的實際類型。

    2,如果類型為空,則判斷是否存在parent bean,如果存在,讀取parent bean的name+"$child"。

    3,如果parent bean 為空,那么判斷是否存在factory bean ,如存在,factory bean name + "$created".前綴生成完畢。

    4,如果前綴為空,直接拋出異常,沒有可以定義這個bean的任何依據。

    5,前綴存在,判斷是否為內部bean(innerBean,此處默認為false),如果是,最終為前綴+分隔符+十六進制的hashcode碼、

    6,如果是頂級bean(top-level bean ),則判斷前綴+數字的bean是否已存在,循環查詢,知道查詢到沒有使用的id為止。處理完成。

  DefaultBeanNameGenerator處理的問題就這些了。

      ?

轉載于:https://www.cnblogs.com/jason0529/p/5272265.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/2/139096.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息