Springソース入門——DefaultBenNameGenerator解析
15857 ワード
私達はspringの中ですべてのbeanがひとつあるべきなことを知っていて、あるいはnameはそれぞれの唯一のbeanを表示して、xmlの中で1つのbeanを定義してそのidとname値を指定することができて、しかしあれらは指定していないで、あるいは注釈のspringのbeannameはどのように来ますか?BenNameGeneratorインターフェースの実現の特性です.
DefaultBeanNameGenerator類は具体的な処理方法を委託しました.BeanDefinitionReaderUtils(咻genersate BeanName(BenDefinition、BenDefinitionRegistry)方法で処理します.
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が扱う問題はこれだけです.
<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が扱う問題はこれだけです.