9、Spring 源码学习 ~ Bean 的加载

Spring 源码学习
摘要由CSDN通过智能技术生成

Bean 的加载

一、整体时序图

1、入口:

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("beanfactory-test.xml"));
TestBean testBean = (TestBean) beanFactory.getBean("testBean");

其中获取 bean 的函数 beanFactory#getBean 就是我们的入口,跟踪入口,可以看到源码如下:

AbstractBeanFactory#getBean

@Override
public Object getBean(String name) throws BeansException {
   
    return doGetBean(name, null, null, false);
}

protected <T> T doGetBean(
    String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
    throws BeansException {
   

    //提取对应的 beanName
    String beanName = transformedBeanName(name);
    Object beanInstance;

    // Eagerly check singleton cache for manually registered singletons.
    // 检查缓存中或者实例工厂中是否有对应的实例
    // 为什么首先会使用这段代码呢?
    // 因为在创建单例 bean 的时候,会存在依赖注入的情况,而创建依赖的时候,为了避免循环依赖
    // Spring 创建 bean 的原则是不等 bean 创建完成,就会将创建 bean 的 ObjectFactory 提早曝光
    // 也就是将 ObjectFactory 加入到缓存中,一旦下个 bean 创建的时候,需要依赖上个 bean 则直接使用 ObjectFactory
    // 下面代码是尝试直接从缓存中获取或者 singletonFactories 中的 ObjectFactory 中获取
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
   
        if (logger.isTraceEnabled()) {
   
            if (isSingletonCurrentlyInCreation(beanName)) {
   
                logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                             "' that is not fully initialized yet - a consequence of a circular reference");
            }
            else {
   
                logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        //返回对应的实例,有时候存在诸如 BeanFactory 的情况,并不是直接返回实例本身,而是返回指定方法返回的实例
        beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
   
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        //只有单例情况下,才会尝试解决循环依赖.
        //如果存在 A 中有属性 B,B 中又有属性 A,那么当依赖注入的时候,
        //就会产生当 A 还未创建完成的时候,由于创建 A 需要先创建 B,而创建 B 又需要先创建 A,
        //就造成了循环依赖,也就是下面 isPrototypeCurrentlyInCreation(beanName) 为 true
        if (isPrototypeCurrentlyInCreation(beanName)) {
   
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        //如果 beanDefinitionMap 中(即所有已加载的类中)不包括 beanName,
        //则尝试从 parentBeanFactory 中检测
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
   
            // Not found -> check parent.
            //递归到 BeanFactory 中寻找
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
   
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                    nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {
   
                //有参,委托给父级
                // Delegation to parent with explicit args.
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else if (requiredType != null) 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值