如何判断IoC容器中是否存在指定Bean?

containsBean方法的作用就是判断IoC容器中是否包含指定名称的Bean。该方法由BeanFactory接口定义,由AbstractBeanFactory实现。

判断IoC容器中是否包含指定beanName是从三个维度去判断的:

一、当前IoC容器的一级缓存(singletonObjects)中是否包含指定beanName的实例;

二、当前IoC容器中是否包含指定beanName的BeanDefinition信息;

三、当前IoC容器如果存在父容器,那么父容器是否存在指定beanName的Bean或者BeanDefinition信息。

了解了判断逻辑后,接下来再分析该方法的执行逻辑就十分简单。在该实现中,首先调用tranforme-dBeanName方法来对传入的name进行处理,接下来便是调用containsSingleton方法来判断当前IoC容器中的一级缓存(singletonObjects)中是否包含指定beanName的实例,调用containsBeanDefinition方法来判断当前IoC容器中是否包含指定beanName的BeanDefinition信息。

如果当前IoC容器中包含指定name的Bean实例或者BeanDefinition,接下来会再做一次验证,判断指定name所对应的Bean类型(注意,这里讲的Bean类型,指的是更宽泛的概念,IoC容器中的Bean大体可以分为两种类型:一种是普通Bean,一种是FactoryBean)。

调用BeanFactoryUtils的isFactoryDereference方法来判断传入的name是否是一个FactoryBean的beanName,注意这里是对判断结果取反。如果该判断不成立,则意味着传入的name所对应的Bean必定是一个FactoryBean,调用isFactoryBean方法来进行验证。

以上是当前IoC容器中存在指定name的Bean实例或者BeanDefinition信息的场景,如果当前IoC容器不存在,那么则判断当前IoC容器其父容器是否不等于空,并调用父容器的containsBean方法,返回父容器的判断结果(这是一个递归查找,假设父容器也有父容器,层层查找)。

// AbstractBeanFactory#containsBean
@Override
public boolean containsBean(String name) {
	String beanName = transformedBeanName(name);
	if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
		return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
	}
	// Not found -> check parent.
	BeanFactory parentBeanFactory = getParentBeanFactory();
	return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
}

// DefaultSingletonBeanRegistry#containsSingleton
@Override
public boolean containsSingleton(String beanName) {
	return this.singletonObjects.containsKey(beanName);
}

// DefaultListableBeanFactory#containsBeanDefinition
@Override
public boolean containsBeanDefinition(String beanName) {
	Assert.notNull(beanName, "Bean name must not be null");
	return this.beanDefinitionMap.containsKey(beanName);
}

BeanFactoryUtils的isFactoryDereference方法实现很简单,判断传入的name不等于空,并且name是以“&”开始。

String FACTORY_BEAN_PREFIX = "&";

public static boolean isFactoryDereference(@Nullable String name) {
   return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
}

isFactoryBean方法由ConfigurableBeanFactory接口定义,由AbstractBeanFactory类实现,在该实现中,首先调用transformedBeanName方法对传入的name进行处理,接下来调用getSingleton方法来获取IoC容器中的一级缓存或二级缓存中是否存在指定beanName的实例,如果存在,则判断是否是FactoryBean类型。

如果getSingleton方法返回值为空,则判断当前IoC容器是否不包含指定beanName的BeanDefinition信息并且当前IoC容器存在父容器并且父容器是ConfigurableBeanFactory类型。如果判断成立,则调用父容器的isFactoryBean方法并返回。

最后调用重载的isFactoryBean方法,首先获取beanName所对应的BeanDefinition,然后根据BeanD-efinition信息来判断指定beanName所对应的Bean是否是一个FactoryBean。

// AbstractBeanFactory#isFactoryBean
@Override
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
   String beanName = transformedBeanName(name);
   Object beanInstance = getSingleton(beanName, false);
   if (beanInstance != null) {
      return (beanInstance instanceof FactoryBean);
   }
   // No singleton instance found -> check bean definition.
   if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
      // No bean definition found in this factory -> delegate to parent.
      return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
   }
   return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}

总结

IoC容器的containsBean方法拥有层次性判断能力,即当前容器→父容器→父容器的父容器…层层进行查找。

用该方法来判断IoC容器中是否包含某个Bean,即使返回值为true,但不代表指定beanName所关联的Bean已经被初始化,因为通过上面代码分析可以得知支撑其判断的数据来源部分是来自beanDefi-nitionMap。

另外通过registerSingleton方法注册的Bean也是支撑IoC容器用来判断的数据来源,因为通过该方法注册的Bean是直接被保存进singletonObjects中,即一级缓存。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值