第二章 第一節 spring-beans之BeanNameGenerator深刻詳解

前言

BeanNameGenerator是beans體系很是重要的一個組件,主要功能是從必定的條件中計算出bean的name.若是出現問題,是能夠規避的。一樣能夠重寫解決。java

/** Map of bean definition objects, keyed by bean name */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);

	/** Map of singleton and non-singleton bean names, keyed by dependency type */
	private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);

	/** Map of singleton-only bean names, keyed by dependency type */
	private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);

	/** List of bean definition names, in registration order */
	private volatile List<String> beanDefinitionNames = new ArrayList<String>(256);

	/** List of names of manually registered singletons, in registration order */
	private volatile Set<String> manualSingletonNames = new LinkedHashSet<String>(16);

	/** Cached array of bean definition names in case of frozen configuration */
	private volatile String[] frozenBeanDefinitionNames;

從上面的數據中能夠看出,bean的管理基本是基於beanName的。因此如何得到beanName是一個重要的關鍵。因此深刻了解BeanNameGenerator體系是十分重要的spring

源碼解讀

BeanNameGenerator

public interface BeanNameGenerator {
	String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry);
}

BeanNameGenerator就一個方法聲明,generateBeanName的聲明並不複雜,傳遞BeanDefinition與BeanDefinitionRegistry 返回一個string類型的beanname。因此本節深刻解讀仍是比較簡單的。api

DefaultBeanNameGenerator

public class DefaultBeanNameGenerator implements BeanNameGenerator {

	@Override
	public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
		return BeanDefinitionReaderUtils.generateBeanName(definition, registry);
	}

}
public static String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
	return generateBeanName(beanDefinition, registry, false);
}

public static String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean) throws BeanDefinitionStoreException {
	// ((Class<?>) beanClassObject).getName() 返回的是 class的徹底限定名
	// 也多是類名
	String generatedBeanName = definition.getBeanClassName();
	if (generatedBeanName == null) {
		if (definition.getParentName() != null) {
			//當generatedBeanName爲null,parentName不爲空。命名方式爲parentName+"$child"
			generatedBeanName = definition.getParentName() + "$child";
		}else if (definition.getFactoryBeanName() != null) {
			//當generatedBeanName爲null,FactoryBeanName不爲空。命名方式爲FactoryBeanName+"$child"
			generatedBeanName = definition.getFactoryBeanName() + "$created";
		}
	}
	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;
	// generatedBeanName + 「#」 + value
	// isInnerBean 爲true.使用系統identityHashCode做爲value,false使用自增的方法做爲value
	if (isInnerBean) {
		// Inner bean: generate identity hashcode suffix.
		id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(definition);
	}else {
		int counter = -1;
		// 到容器裏面看看是否存在一樣名字的BeanDefinition
		while (counter == -1 || registry.containsBeanDefinition(id)) {
			counter++;
			id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + counter;
		}
	}
	return id;
}
beanName 生成規則

AnnotationBeanNameGenerator

public class AnnotationBeanNameGenerator implements BeanNameGenerator {

	private static final String COMPONENT_ANNOTATION_CLASSNAME = "org.springframework.stereotype.Component";

	@Override
	public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
		// 判斷是AnnotatedBeanDefinition的實現,就從annotation得到。
		if (definition instanceof AnnotatedBeanDefinition) {
			String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
			// 是文本就返回這個beanName,可是也有可能annotation的value是null,就後從buildDefaultBeanName得到
			if (StringUtils.hasText(beanName)) {
				return beanName;
			}
		}
		return buildDefaultBeanName(definition, registry);
	}

	protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
		// 得到類或者方法上全部的Annotation
		AnnotationMetadata amd = annotatedDef.getMetadata();
		// 獲得全部annotation的類名
		Set<String> types = amd.getAnnotationTypes();
		String beanName = null;
		for (String type : types) {
			// 把annotation裏面的字段與value,解讀出來成map,字段名是key,value爲value
			AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
			// 判斷annotation是否有效,是否存在做爲beanName的字段有value
			if (isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) {
				// 從註解中得到value字段的值,
				Object value = attributes.get("value");
				if (value instanceof String) {
					String strVal = (String) value;
					if (StringUtils.hasLength(strVal)) {
						if (beanName != null && !strVal.equals(beanName)) {
							throw new IllegalStateException("Stereotype annotations suggest inconsistent " +"component names: '" + beanName + "' versus '" + strVal + "'");
						}
						beanName = strVal;
					}
				}
			}
		}
		return beanName;
	}

	
	protected boolean isStereotypeWithNameValue(String annotationType,Set<String> metaAnnotationTypes, Map<String, Object> attributes) {
		// 判斷annotation的類型是不是這三種.
		// org.springframework.stereotype.Component
		// javax.annotation.ManagedBean
		// javax.inject.Named
		
		boolean isStereotype = annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME) ||
				(metaAnnotationTypes != null && metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME)) ||
				annotationType.equals("javax.annotation.ManagedBean") ||
				annotationType.equals("javax.inject.Named");
		// 而且value存在值。纔會返回true
		return (isStereotype && attributes != null && attributes.containsKey("value"));
	}

	
	protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
		return buildDefaultBeanName(definition);
	}

	
	protected String buildDefaultBeanName(BeanDefinition definition) {
		// 得到類名
		String shortClassName = ClassUtils.getShortName(definition.getBeanClassName());
		// 把類名第一個字母大寫轉小寫
		return Introspector.decapitalize(shortClassName);
	}

}

掃描的註解有

org.springframework.stereotype.Component#value() org.springframework.stereotype.Repository#value() org.springframework.stereotype.Service#value() org.springframework.stereotype.Controller#value() javax.inject.Named#value() javax.annotation.ManagedBean#value()ide

當註解的value字段不存在值的時候,會默認把首字母小寫的類名作的beanNameui

使用詳解

往ApplicationContext註冊BeanNameGeneratord對象

AnnotationConfigApplicationContext
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
		this.reader.setBeanNameGenerator(beanNameGenerator);
		this.scanner.setBeanNameGenerator(beanNameGenerator);
		getBeanFactory().registerSingleton(
				AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
	}
AnnotationConfigWebApplicationContext
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
		this.beanNameGenerator = beanNameGenerator;
	}

經過beanName從ApplicationContext得到對象

@Override
public Object getBean(String name) throws BeansException {
	assertBeanFactoryActive();
	return getBeanFactory().getBean(name);
}

@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
	assertBeanFactoryActive();
	return getBeanFactory().getBean(name, requiredType);
}

經過beanName從BeanFactory得到對象

@Override
public Object getBean(String name) throws BeansException {
	return getBean(name, Object.class);
}

@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
	try {
		if (isSingleton(name)) {
			return doGetSingleton(name, requiredType);
		}
		else {
			return lookup(name, requiredType);
		}
	}
	catch (NameNotFoundException ex) {
		throw new NoSuchBeanDefinitionException(name, "not found in JNDI environment");
	}
	catch (TypeMismatchNamingException ex) {
		throw new BeanNotOfRequiredTypeException(name, ex.getRequiredType(), ex.getActualType());
	}
	catch (NamingException ex) {
		throw new BeanDefinitionStoreException("JNDI environment", name, "JNDI lookup failed", ex);
	}
}
private <T> T doGetSingleton(String name, Class<T> requiredType) throws NamingException {
	synchronized (this.singletonObjects) {
		if (this.singletonObjects.containsKey(name)) {
			Object jndiObject = this.singletonObjects.get(name);
			if (requiredType != null && !requiredType.isInstance(jndiObject)) {
				throw new TypeMismatchNamingException(
						convertJndiName(name), requiredType, (jndiObject != null ? jndiObject.getClass() : null));
			}
			return (T) jndiObject;
		}
		T jndiObject = lookup(name, requiredType);
		this.singletonObjects.put(name, jndiObject);
		return jndiObject;
	}
}
相關文章
相關標籤/搜索