SpringBoot 装配 List 时遇到的一个问题

我们知道,Spring在遇到类型为 List、Map 之类的属性时,会根据类型收集容器内的所有Bean然后进行注入:

@Service
public class MainServiceImpl implement MainService{
  // 当装配对象类型为 List 时,会根据泛型收集容器内的所有bean,并注入
  @Autowired
  List<MainRepository> repository;
}

今天遇到一位大牛写的代码,写了这样一段自己注入自己类型的代码:

@Primary
@Service
public class MainServiceImpl implement MainService{
  // 当装配对象类型为 List 时,会根据泛型收集容器内的所有bean,并注入
  @Autowired
  List<MainService> service;
}

从上面我们可以看到 MainServiceImpl 实现了 MainService,然后在自动装配中又注入了 MainService 类型的对象.

实现了 MainService 接口的组件还有两个,分别是 Main1ServiceImplMainServiceImpl,照上面的代码来理解的话,在自动装配完成后 List 中会包含三个组件:

MainServiceImpl
Main1ServiceImpl
Main2ServiceImpl

也即 MainServiceImpl 中会出现自己依赖自己的情况。但实际实现过程中,List 中只有两个组件,分别是Main1ServiceImplMain2ServiceImpl,并没有出现自己依赖自己的问题。仔细想来,应该是Spring为我们处理了这些情况,因此找来了源码做了一下分析。

入口在 BeanFactory 中,Spring在实例化 Bean 完成之后,需要为 Bean 注入组件,当注入类型为 List 类型的时候,会从容器中获取到所有符合条件的 组件,然后将自身引用剔除掉.

AbstractBeanFactory DefaultSingletonBeanRegistry AbstractAutowireCapableBeanFactory AutowiredAnnotationBeanPostProcessor InjectionMetadata DefaultListableBeanFactory getBean doGetBean getSingleton doGetBean createBean doCreateBean populateBean postProcessProperties inject inject resolveFieldValue resolveDependency doResolveDependency resolveMultipleBeans findAutowireCandidates isSelfReference AbstractBeanFactory DefaultSingletonBeanRegistry AbstractAutowireCapableBeanFactory AutowiredAnnotationBeanPostProcessor InjectionMetadata DefaultListableBeanFactory Bean 注入时序图
// DefaultListableBeanFactory#resolveMultipleBeans:1437
// 当发现类型为 Collection 类型时,获取泛型中的元素类型,并通过类型获取匹配bean
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
    Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
    if (elementType == null) {
        return null;
    }
    // 并通过类型获取匹配对象
    Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
            new MultiElementDescriptor(descriptor));
    if (matchingBeans.isEmpty()) {
        return null;
    }

在根据元素类型获取匹配对象的时候会进行是否自引用校验:

// DefaultListableBeanFactory#findAutowireCandidates:1569
for (String candidate : candidateNames) {
  // 判断是否自引用校验,如果不是自引用校验的话加入对象
    if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
        addCandidateEntry(result, candidate, descriptor, requiredType);
    }
}

也就是Spring在进行自动注入的时候,如果发现自引用,会将自引用剔除掉.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值