第二章 第一节 spring-beans之BeanNameGenerator深入详解

前言

BeanNameGenerator是beans体系非常重要的一个组件,主要功能是从一定的条件中计算出bean的name.如果出现问题,是可以规避的。同样可以重写解决。

/** 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体系是十分重要的

源码解读

BeanNameGenerator

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

BeanNameGenerator就一个方法声明,generateBeanName的声明并不复杂,传递BeanDefinition与BeanDefinitionRegistry 返回一个string类型的beanname。所以本节深入解读还是比较简单的。

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()

当注解的value字段不存在值的时候,会默认把首字母小写的类名做的beanName

使用详解

往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;
	}
}

猜你喜欢

转载自my.oschina.net/u/1261452/blog/1801885