本文包括bean name实现类源码详解,及自定义bean name生成策略源码原理详解
bean name生成策略三个实现类源码详解
BeanNameGenerator接口是BeanDefinition定义生成bean名称的策略接口;
public interface BeanNameGenerator {
/**
* 为给定的BeanDefinition生成一个bean名称
*/
String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry);
}
看下BeanNameGenerator接口实现类UML关系图:
DefaultBeanNameGenerator是BeanNameGenerator接口的默认实现类:
public class DefaultBeanNameGenerator implements BeanNameGenerator {
/**
* DefaultBeanNameGenerator实例常量,用于在AbstractBeanDefinitionReader类中属性beanNameGenerator的设置
*/
public static final DefaultBeanNameGenerator INSTANCE = new DefaultBeanNameGenerator();
//通过BeanDefinitionReaderUtils工具类的generateBeanName方法生成指定BeanDefinition的bean名称
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return BeanDefinitionReaderUtils.generateBeanName(definition, registry);
}
}
BeanDefinitionReaderUtils#generateBeanName代理方法源码:
/**
* 为给定的顶级BeanDefinition定义生成一个bean名称,该名称在给定的bean工厂中是唯一的
*/
public static String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
return generateBeanName(beanDefinition, registry, false);
}
/**
* 为给定的顶级BeanDefinition定义生成一个bean名称,该名称在给定的bean工厂中是唯一的
* @param BeanDefiniton定义
* @param 注册bean的工厂类
* @param isInnerBean 给定的BeanDefinition是注册为内部bean还是顶级bean(允许内部bean和顶级bean生成特殊名称)
*/
public static String generateBeanName(
BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean)
throws BeanDefinitionStoreException {
//获取bean定义的类名
String generatedBeanName = definition.getBeanClassName();
if (generatedBeanName == null) {
if (definition.getParentName() != null) {
//当bean定义名称不存在并且存在父类时命名方式
generatedBeanName = definition.getParentName() + "$child";
}
else if (definition.getFactoryBeanName() != null) {
//读取生成该bean的factoryBean名称做前缀
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");
}
if (isInnerBean) {
// 当为内部类时使用#好分割和系统的唯一hash码作为后缀
return generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(definition);
}
// 顶级bean,使用普通类名加唯一后缀
return uniqueBeanName(generatedBeanName, registry);
}
/**
* 将给定的bean名称转换为给定bean工厂的唯一bean名称,如果有必要,附加一个唯一的计数器做后缀
*/
public static String uniqueBeanName(String beanName, BeanDefinitionRegistry registry) {
String id = beanName;
int counter = -1;
// 增加计数器,直到id唯一
String prefix = beanName + GENERATED_BEAN_NAME_SEPARATOR;
while (counter == -1 || registry.containsBeanDefinition(id)) {
counter++;
id = prefix + counter;
}
return id;
}
AnnotationBeanNameGenerator是BeanNameGenerator接口的实现类,用来生成被@Component注解或者其它@Component派生注解标注的bean;示例:被@Component注解标注的@Repository注解。
如果注释的值没有指示bean名称,那么将基于类的短名称(第一个字母消息)构建一个适当的名称。例如:com.xyz.FooServiceImpl类的bean名称是fooServiceImpl。
AnnotationBeanNameGenerator类源码:
public class AnnotationBeanNameGenerator implements BeanNameGenerator {
/**
* 默认AnnotationBeanNameGenerator实例的方便常量,用于组件扫描目的(即@Componment注解及@ComponmentScan注解扫描包)bean名称生成
* @since 5.2
*/
public static final AnnotationBeanNameGenerator INSTANCE = new AnnotationBeanNameGenerator();
//@Component注解类常量
private static final String COMPONENT_ANNOTATION_CLASSNAME = "org.springframework.stereotype.Component";
private final Map<String, Set<String>> metaAnnotationTypesCache = new ConcurrentHashMap<>();
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
if (definition instanceof AnnotatedBeanDefinition) {
//通过注解的属性值获取bean名称
String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
if (StringUtils.hasText(beanName)) {
//显式的找到bean名称
return beanName;
}
}
//如果注解未指定bean名称,则生成一个唯一的默认bean名称
return buildDefaultBeanName(definition, registry);
}
/**
* 从类上的一个注释派生bean名称(即通过注解的属性value值来获取唯一的bean名称)
* @param annotatedDef the annotation-aware bean definition
* @return the bean name, or {@code null} if none is found
*/
@Nullable
protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
AnnotationMetadata amd = annotatedDef.getMetadata();
Set<String> types = amd.getAnnotationTypes();
String beanName = null;
for (String type : types) {
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
if (attributes != null) {
Set<String> metaTypes = this.metaAnnotationTypesCache.computeIfAbsent(type, key -> {
Set<String> result = amd.getMetaAnnotationTypes(key);
return (result.isEmpty() ? Collections.emptySet() : result);
});
//检查给定的注释是否允许通过其注释的value属性构造bean名称
if (isStereotypeWithNameValue(type, metaTypes, attributes)) {
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;
}
/**
* 检查给定的注释是否允许通过其注释的value属性构造bean名称
*/
protected boolean isStereotypeWithNameValue(String annotationType,
Set<String> metaAnnotationTypes, @Nullable Map<String, Object> attributes) {
boolean isStereotype = annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME) ||
metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME) ||
annotationType.equals("javax.annotation.ManagedBean") ||
annotationType.equals("javax.inject.Named");
return (isStereotype && attributes != null && attributes.containsKey("value"));
}
/**
* 从给定的bean定义派生一个默认的bean名称,即类名首字母小写
*/
protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return buildDefaultBeanName(definition);
}
/**
* 从给定的bean定义派生一个默认的bean名称,即类名首字母小写
*/
protected String buildDefaultBeanName(BeanDefinition definition) {
String beanClassName = definition.getBeanClassName();
Assert.state(beanClassName != null, "No bean class name set");
String shortClassName = ClassUtils.getShortName(beanClassName);
return Introspector.decapitalize(shortClassName);
}
}
FullyQualifiedAnnotationBeanNameGenerator类源码:
FullyQualifiedAnnotationBeanNameGenerator类是AnnotationBeanNameGenerator类的一个扩展用于生成类的全限定类名作为bean名称,
public class FullyQualifiedAnnotationBeanNameGenerator extends AnnotationBeanNameGenerator {
@Override
protected String buildDefaultBeanName(BeanDefinition definition) {
String beanClassName = definition.getBeanClassName();
Assert.state(beanClassName != null, "No bean class name set");
return beanClassName;
}
}
bean name自定义生成策略源码原理解析
在后置beanfactory容器回调接口实现类ConfigurationClassPostProcessor中定义有三个变量:
//使用类的全限定名作为bean的默认生成策略
public static final AnnotationBeanNameGenerator IMPORT_BEAN_NAME_GENERATOR =
new FullyQualifiedAnnotationBeanNameGenerator();
/* 使用短类名作为默认bean名称生成策略 */
private BeanNameGenerator componentScanBeanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
/* 使用类的全新定名作为bean默认生成策略 */
private BeanNameGenerator importBeanNameGenerator = IMPORT_BEAN_NAME_GENERATOR;
//是否是本地xml配置的BeanNameGenerator生成器
private boolean localBeanNameGeneratorSet = false;
ConfigurationClassPostProcessor#setBeanNameGenerator方法设置自定义bean name生成器,这个setter通常只适用于将ConfigurationClassPostProcessor后处理器配置为XML中的独立bean定义,例如:不使用专用的AnnotatiionConfig*应用程序上下文或者context:annotation-config标签,针对应用程序上下文指定的任何bean名称生成器都将优先于此处的设置(此方法只适合Spring中通过xml配置的形式,springboot可以忽略)。
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
Assert.notNull(beanNameGenerator, "BeanNameGenerator must not be null");
this.localBeanNameGeneratorSet = true;
this.componentScanBeanNameGenerator = beanNameGenerator;
this.importBeanNameGenerator = beanNameGenerator;
}
ConfigurationClassPostProcessor#processConfigBeanDefinitions方法(只展示bean name名称生成策略部分代码):
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
...
//检测通过封闭的应用程序上下文提供的任何自定义bean名称生成策略
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
//springboot 中localBeanNameGeneratorSet默认是false
if (!this.localBeanNameGeneratorSet) {
//获取自定义的bean name生成策略
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
//设置组件扫描bean name生成策略
this.componentScanBeanNameGenerator = generator;
//设置import bean name生成策略
this.importBeanNameGenerator = generator;
}
}
}
...
}
到这里会有一个疑问内部自定义bean name生成策略bean org.springframework.context.annotation.internalConfigurationBeanNameGenerator(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR)是如何注入到IOC容器之中的?那我们看下启动类SpringApplication#run方法,方法中内嵌prepareContext方法,prepareContext方法内嵌postProcessApplicationContext方法:
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
//此处会判定bean name生成策略是否为空
if (this.beanNameGenerator != null) {
//此处 将上一步中的疑问,自定义bean name生成策略注入到IOC容器
context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,this.beanNameGenerator);
}
。。。
}
此段代码我们看到了如何将bean name自定义生成策略注入到IOC容器之中,那么beanNameGenerator生成策略是如何获取呢?beanNameGenerator是SpringApplication类的一个属性,提供了setter方法:
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
this.beanNameGenerator = beanNameGenerator;
}
此处的setter方法就是我们设置自定义bean name生成器的入口,示例如下:
@SpringBootApplication
public class QuartzBootStrap {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(QuartzBootStrap.class);
//MySelfBeanNameGenerator是自定义bean name生成策略
application.setBeanNameGenerator(new MySelfBeanNameGenerator());
application.run(args);
}
}
至此,springboot如何自定义bean name生成策略,此处的设置是全局的,不包括指定配置类的bean name生成策略。
自定义生成bean name策略实现类:
public class MySelfBeanNameGenerator implements BeanNameGenerator {
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
System.out.println("--------"+definition.getBeanClassName());
return definition.getBeanClassName();
}
}