Spring基础篇-BeanName的生成原理分析(源码)!

在Spring中,提供了BeanNameGenerator来生成BeanName.

public interface BeanNameGenerator {
    String generateBeanName(BeanDefinition var1, BeanDefinitionRegistry var2);
}

查看关系图,我们可以看到。
在这里插入图片描述

DefaultBeanNameGenerator

XML配置中,默认生成BeanName。

public class DefaultBeanNameGenerator implements BeanNameGenerator {
    public static final DefaultBeanNameGenerator INSTANCE = new DefaultBeanNameGenerator();

    public DefaultBeanNameGenerator() {
    }

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

我们可以看到,DefaultBeanNameGenerator这个类内部,实际上是generateBeanName这个方法去通过 BeanDefinitionReaderUtils.generateBeanName(definition, registry);去生成BeanName的。

   public static String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean) throws BeanDefinitionStoreException {
   //从xml文件中获取到BeanName
        String generatedBeanName = definition.getBeanClassName();
        if (generatedBeanName == null) {
        //如果BeanName为null则去获取他的父类,通过父类名+$child组成BeanName
            if (definition.getParentName() != null) {
                generatedBeanName = definition.getParentName() + "$child";
            } else if (definition.getFactoryBeanName() != null)//如果父类名也没有,则使用factoryBeanName尝试获取 {
                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");
        } else {
        //否则,调用uniqueBeanName方法去生成BeanName.
            return isInnerBean ? generatedBeanName + "#" + ObjectUtils.getIdentityHexString(definition) : uniqueBeanName(generatedBeanName, registry);
        }
    }
 public static String uniqueBeanName(String beanName, BeanDefinitionRegistry registry) {
        String id = beanName;
        int counter = -1;

//将类的全路径和#拼在一起,并且判断id是否已被注册,如果注册,则下一个,生成一个新的id.
        for(String prefix = beanName + "#"; counter == -1 || registry.containsBeanDefinition(id); id = prefix + counter) {
            ++counter;
        }

        return id;
    }

AnnotationBeanNameGenerator

Java配置中,如果使用了@Component注解,则使用这个来生成BeanName.

我们可以看到,在使用Java配置的时候,一般只使用一个@Bean()注解,实际上,点进去查看,就会发现,@Bean()注解内部已经使用了@Component注解。


@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean {}

Id和Name的处理原理

id和Name的属性处理也是在BeanDefinitionParserDelegate#parseBeanDefinitionElement这个方法中,获取id和name,
如果nameAttr有参数,则基于,空格等格式进行拆分,然后将拆出来的属性,作为bean的别名。
下面,if则进行判断,没有id属性,但是有name属性,则将拆出来的第一项,作为beanName.

   String id = ele.getAttribute("id");
        String nameAttr = ele.getAttribute("name");
        List<String> aliases = new ArrayList();
        if (StringUtils.hasLength(nameAttr)) {
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
            aliases.addAll(Arrays.asList(nameArr));
        }

        String beanName = id;
        if (!StringUtils.hasText(id) && !aliases.isEmpty()) {
            beanName = (String)aliases.remove(0);
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");
            }
        }

如果经过以上的处理,beanName还是空的,则进入到之前的循环,系统自动给定一个BeanName.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值