bean加载一:转换beanName、循环依赖、实例化

本文会介绍上文中提到的<1>,<2>,<3>这三个步骤的内容

1 transformedBeanName

  final String beanName = transformedBeanName(name);

这段代码的作用主要有两个:
1.如果传入的bean name是别名,那么就要获取对应的真实的bean name。也会存在循环别名即别名B指向别名A,别名A指向真实的bean name的情况。
2.去掉"&"符号,获取真实的bean name。如:name从"&MyBean"变成"MyBean"。

protected String transformedBeanName(String name) {
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

public static String transformedBeanName(String name) {
    Assert.notNull(name, "'name' must not be null");
    if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        return name;
    }
    // 循环去掉前面所有的 & 符号
    return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
        do {
            beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        }
        while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
        return beanName;
    });
}

public String canonicalName(String name) {
    String canonicalName = name;
    // Handle aliasing...
    String resolvedName;
    do {
        // 递归获取别名对应的beanName
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    }
    while (resolvedName != null);
    return canonicalName;
}

2 getSingleton

spring为了避免创建单例时出现循环依赖的问题,所以创建bean的时候不等bean创建完成就会创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时需要依赖这个bean就直接使用ObjectFactory。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 从单例缓存中加载 bean
    Object singletonObject = this.singletonObjects.get(beanName);
    // 缓存中的 bean 为空,且当前 bean 正在创建(注:第七步创建单例类型bean的时候会保存在一个缓存中)
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            // 从 earlySingletonObjects 获取,表示此bean正在创建,不进行后续处理
            singletonObject = this.earlySingletonObjects.get(beanName);
            // earlySingletonObjects 中没有,且允许提前创建
            if (singletonObject == null && allowEarlyReference) {
                // 从 singletonFactories 中获取对应的 ObjectFactory
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    // 获得 bean
                    // 对应第7步中的 getEarlyBeanReference(beanName, mbd, bean)
                    singletonObject = singletonFactory.getObject();
                    // 添加 bean 到 earlySingletonObjects 中
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    // 从 singletonFactories 中移除对应的 ObjectFactory
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

最大的难点可能在于其中的好几个map对象到底是什么意思,下面来简单介绍下:
1.singletonObjects(一级缓存):保存beanName与bean实例之间的关系。
那么这个里面的数据来自哪里呢?答案在 bean 加载过程中的第7步

DefaultSingletonBeanRegistry#getSingleton(创建单例模式的java bean)
-> DefaultSingletonBeanRegistry#addSingleton方法

protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        this.singletonObjects.put(beanName, singletonObject);
        this.singletonFactories.remove(beanName);
        this.earlySingletonObjects.remove(beanName);
        this.registeredSingletons.add(beanName);
    }
}

从二级和三级缓存中删除,添加到一级缓存中
2.earlySingletonObjects(二级缓存):也是保存beanName与bean实例之间的关系,与singletonObjects不同的地方是,当bean还在创建过程中的时候就可以通过这个map拿到对应的bean实例,相当于保存的是半成品的bean,用来检测循环引用。
3.singletonFactories(三级缓存):保存beanName与创建bean的工厂之间的关系。这个map中的数据来源于,bean 加载过程中的第7步

AbstractAutowireCapableBeanFactory#createBean
-> AbstractAutowireCapableBeanFactory#doCreateBean
-> DefaultSingletonBeanRegistry#addSingletonFactory

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    synchronized (this.singletonObjects) {
        if (!this.singletonObjects.containsKey(beanName)) {
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}

从三级缓存中删除,加入二级缓存。由此可以看到二级缓存和三级缓存其实是互斥的

总的三级缓存的使用逻辑大概是
在A的创建过程中会添加三级缓存,然后进行A的属性填充,如果此时A依赖了B,那么需要首先创建B。当B的创建又需要用到A,就会从三级缓存中获取,然后通过singletonFactory.getObject()获取初始A对象(没有初始化和填充属性,但是经过了AOP代理),放入二级缓存并且删除三级缓存,返回半成品的A作为B的属性,然后B的创建就完成了。返回A的创建中,当A创建完成后,删除二级和三级缓存,之后的A获取都可以在一级缓存中拿到。
从这里可以看出来,就算是使用一级和二级缓存也能实现解决循环依赖的问题,那为什么还要使用三级缓存呢?原因主要是:二级缓存放入的是实例化后的半成品对象,如果这个对象还需要实现AOP功能,那么就需要使用ObjectFactory包装然后放入三级缓存中。然后在第三步的getObjectForBeanInstance方法中,取出ObjectFactory包装的AOP之后的对象。

3 getObjectForBeanInstance

protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

    // 若为工厂类引用(name 以 & 开头)
    // Don't let calling code try to dereference the factory if the bean isn't a factory.
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        // 类型不为 FactoryBean
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
        }
    }

    // 到这里就有了一个 Bean 实例,当然该实例可能是会是一个正常的 bean 又或者是一个 FactoryBean
    // 如果是 FactoryBean 并且 name 中有 & 符号,则直接返回,否则使用 FactoryBean 创建bean
    // Now we have the bean instance, which may be a normal bean or a FactoryBean.
    // If it's a FactoryBean, we use it to create a bean instance, unless the
    // caller actually wants a reference to the factory.
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

    Object object = null;
    // 若 BeanDefinition 为 null,则从缓存中加载 Bean 对象
    if (mbd == null) {
        object = getCachedObjectForFactoryBean(beanName);
    }
    // 若 object 依然为空,则可以确认,beanInstance 一定是 FactoryBean 。从而,使用 FactoryBean 获得 Bean 对象
    if (object == null) {
        // Return bean instance from factory.
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        // containsBeanDefinition 检测 beanDefinitionMap 中也就是在所有已经加载的类中
        // 检测所有已经加载的bean是否包含 beanName
        if (mbd == null && containsBeanDefinition(beanName)) {
            // 将存储 XML 配置文件的 GenericBeanDefinition 转换为 RootBeanDefinition,
            // 如果指定 BeanName 是子 Bean 的话同时会合并父类的相关属性
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        // 是否是用户定义的,而不是应用程序本身定义的
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        // 核心处理方法,使用 FactoryBean 获得 Bean 对象
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

其中最核心的是getObjectFromFactoryBean,接下来看看这个方法。

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    // 为单例模式且缓存中存在
    if (factory.isSingleton() && containsSingleton(beanName)) {
        synchronized (getSingletonMutex()) {
            // 从缓存中获取指定的 factoryBean
            Object object = this.factoryBeanObjectCache.get(beanName);
            if (object == null) {
                // 为空,则从 FactoryBean 中获取对象
                object = doGetObjectFromFactoryBean(factory, beanName);
                // Only post-process and store if not put there already during getObject() call above
                // (e.g. because of circular reference processing triggered by custom getBean calls)
                Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                if (alreadyThere != null) {
                    object = alreadyThere;
                }
                else {
                    // 需要后续处理
                    if (shouldPostProcess) {
                        // 若该 Bean 处于创建中,则返回非处理对象,而不是存储它
                        if (isSingletonCurrentlyInCreation(beanName)) {
                            // Temporarily return non-post-processed object, not storing it yet..
                            return object;
                        }
                        // 单例 Bean 的前置处理
                        // 设置该bean正在创建过程中
                        beforeSingletonCreation(beanName);
                        try {
                            // 对从 FactoryBean 获取的对象进行后处理
                            // 生成的对象将暴露给 bean 引用
                            object = postProcessObjectFromFactoryBean(object, beanName);
                        }
                        catch (Throwable ex) {
                            throw new BeanCreationException(beanName,
                                    "Post-processing of FactoryBean's singleton object failed", ex);
                        }
                        finally {
                            // 单例 Bean 的后置处理
                            // 移除该bean正在创建
                            afterSingletonCreation(beanName);
                        }
                    }
                    // 添加到 factoryBeanObjectCache 中,进行缓存
                    if (containsSingleton(beanName)) {
                        this.factoryBeanObjectCache.put(beanName, object);
                    }
                }
            }
            return object;
        }
    }
    else {
        // 为空,则从 FactoryBean 中获取对象
        Object object = doGetObjectFromFactoryBean(factory, beanName);
        // 需要后续处理
        if (shouldPostProcess) {
            try {
                // 对从 FactoryBean 获取的对象进行后处理
                // 生成的对象将暴露给 bean 引用
                object = postProcessObjectFromFactoryBean(object, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
            }
        }
        return object;
    }
}

这里把这个代码拆分成if和else看。

3.1 if块代码

当bean是单例的并且已经存在缓存中。获取同步锁,如果能够获取到对应的FactoryBean就直接返回,否则通过传入的factory#getObject获取对象并且进行后置处理。

3.1.1 doGetObjectFromFactoryBean

权限验证以及通过 factory#getObject 方法获取对象。

3.1.2 后置处理

3.1.2.1 beforeSingletonCreation

protected void beforeSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    }

校验当前bean没有在检测并且设置正在创建

3.1.2.2 postProcessObjectFromFactoryBean

    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        // 获取 BeanPostProcessor 数组
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            // 循环调用 postProcessAfterInitialization 方法,如果为空立即返回
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

BeanPostProcessor 也就是后置处理器,可用于类增强。后续专门介绍

3.1.2.3 afterSingletonCreation

校验当前bean没有在检测并且移除正在创建

3.2 else

bean不是单例对象,直接通过 factory#getObject 方法获取对象,并且进行后置处理。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。