Springソース入門——DefaultBenNameGenerator解析

15857 ワード

私達はspringの中ですべてのbeanがひとつあるべきなことを知っていて、あるいはnameはそれぞれの唯一のbeanを表示して、xmlの中で1つのbeanを定義してそのidとname値を指定することができて、しかしあれらは指定していないで、あるいは注釈のspringのbeannameはどのように来ますか?BenNameGeneratorインターフェースの実現の特性です.
  <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
BenNameGeneratorインターフェースはorg.springframe ebork.beans.factory.supportパッケージの下に位置しています.二つのパラメータを受け入れます.definitionは名前を生成されたBenDefinitionの例です.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);
 BenNameGeneratorは2つの実装バージョンがあります.DefaultBeanNameGeneratorとAnnotationBeanNameGenerator.その中でDefaultBeanNameGeneratorは資源ファイルにbeanをロードする時使います.AnnotationBeanNameGeneratorは注釈を処理するためにbean nameを生成する場合です.
DefaultBeanNameGenerator類は具体的な処理方法を委託しました.BeanDefinitionReaderUtils(咻genersate BeanName(BenDefinition、BenDefinitionRegistry)方法で処理します.  
    /**
     * 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);
    }
この方法は何の処理もしていません.直接にゲナートビーンName(BenDefinition、BenDefinitionRegistry、bootlean)メソッドに委託しました.ブックレン型パラメータを指定したのは内部beanとトップ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,       +    ,        id
        else {
            // 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であるかどうかを判断します.ここではデフォルトfalseです.もし、最終的にプレフィックス+セパレータ+16進数のhashcodeコード、
6,トップレベルのbeanであれば、プレフィックス+数字のbeanが既に存在しているかどうかを判断し、巡回クエリし、使用されていないidが確認されるまで処理が完了する.
DefaultBeanNameGeneratorが扱う問題はこれだけです.