spring是如何给bean起名字的(多图巨细长文)

首先我们创建两个类,需要被加载的bean和启动类

package scan;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Service;

//单例多例
@Scope("prototype")
/**
 * @see AbstractBeanDefinition
 * Set a human-readable description of this bean definition.
 */
@Description("dao")
//优先被注入
@Primary
//实例化条件
@Conditional(value = {TestCondition.class})
@Lazy(value = false)
@Service
public class TestBean {

    //根据类型自动的注入对象,如果该类型对象是多个的时候可以结合@Qualifier注解指定的beanId
//    @Autowired
//    @Qualifier("tempBean")
//    TempBean tempBean;

}
package scan;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestApplication {

    /**
     * @author code-generator
     */

    public static void main(String[] args) {

        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(TestBean.class);
//        applicationContext.scan("");
        applicationContext.getBean("testBean");

    }

}

点击AnnotationConfigApplicationContext一路往下走会发现beanName事由如下代码生成:

String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

beanNameGenerator有两个实现,由于我们用的是注解的方法,所以用的是AnnotationBeanNameGenerator来处理

进去看generateBeanName

首先判断了definition 是否是 AnnotatedBeanDefinition的一个实例,我们看下面的继承树,发现判断成立

进入if代码块,我们去看determineBeanNameFromAnnotation这个方法

首先获取到了加在bean上的注解,然后循环加在bean上的注解,判断这个注解是否是可以给bean命名的注解,我们看下面的图

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

代码很明确,如果这个注解为

1.COMPONENT_ANNOTATION_CLASSNAME或者javax.annotation.ManagedBean或者javax.inject.Named或者2.metaAnnotationTypes这个set包含COMPONENT_ANNOTATION_CLASSNAME

并且3.这个注解上面的注解不能为空,并且4.这个注解要有value值

以@scope为例3和4是满足的,1不满足,但是只要1和2满足其一就代表成立,那么2这个metaAnnotationTypes set是个什么东西呢,我们去看getMetaAnnotationTypes这个方法

一路往下走

下面这个方法把annotationName(注解名称)转换成了注解类,继续

触发方法来喽,看到metaAnnotationTypes这个set了吧,就是下面的types

我们进入searchWithGetSemantics这个方法,我们发现visited是一个HashSet,if (visited.add(element))来过滤这个AnnotatedElement是否被处理过,因为hashset在add的时候如果set中已经存在,会返回false,这个判断就是用来过滤防止同样的AnnotatedElement被重复处理(一不小心跳过了一次循环跑到@Description这个注解了,一样的)

进入searchWithGetSemanticsInAnnotations这个方法,先看上半部分

进入AnnotationUtils.isInJavaLangAnnotationPackage方法

发现判断是否是这个注解名字不为空,并且是以java.lang.annotation开头的,显然@description符合条件,但是前面加了!,所以@description不能给这个bean命名

我们看下代码下半部分,仍然是循环处理加在@description上面的注解,首先我们看一下这个方法hasSearchableMetaAnnotations

这个方法作用是优化下面的递归,简单来说就是有一些注解已经明确知道不能用来命名了,就没有意义继续递归下去,节省资源

如果通过了hasSearchableMetaAnnotations校验,根据注释我们可以得知,下半部分代码是递归去调用上面的searchWithGetSemantics方法也就是说,递归的去遍历加在@description上面的注解里的注解是否由符合条件给bean命名的,然后一直往上找,然而@description和加在他上面的注解以及一直查到根也没能找到符合条件的注解,所以@description并不能给bean命名。继续往下走,我们看下@service这个注解

@org.springframework.stereotype.Component这个注解通过了校验,把它加入到types这个set中,目前types中有了一个,继续往下走会递归加在@service上的注解一直到根,由于只有Component注解通过了校验,下面代码就会递归加在Component注解上的注解

加在component上的注解里面又有@indexed是符合条件的,把它加入到types这个set中,目前types中有了两个,然后会继续递归@indexed,显然加在index上的注解没有通过校验的,到此校验全部结束

我们回头看一下上面代码,@service的getMetaAnnotationTypes是不是获取到了这两个

metaAnnotationTypes包含了org.springframework.stereotype.Component所以说明@service是有能力为bean命名的,接着我们要获取@service中的value的值,这个值就是将来生成bean的名字,然而我们没有给value值,所以获取到了一个空字符串,下面代码没有获取到名字,就返回了一个null

generateBeanName代码中发现通过注解获取bean名字失败了,就只能通过buildDefaultBeanName生成一个默认的名字

首先通过BeanDefinition获取到beanClassName,然后获取shortname,其实就是获取这个class的类名,最后Introspector.decapitalize(shortClassName)这个方法是类名首字母小写

至此bean命名全部结束

好了,没了!

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值