当前位置 博文首页 > 北漂程序员:一次性讲清楚spring中bean的生命周期之二:FactoryB

    北漂程序员:一次性讲清楚spring中bean的生命周期之二:FactoryB

    作者:北漂程序员 时间:2021-07-02 18:28

    前言

    在《spring中FactoryBean是什么bean》一文中,带着小伙伴学习了spring中的FactoryBean,了解了到了FactoryBean其实是一种生产Bean的bean,也就是FactroyBean的前世是Bean,今生还是Bean,小伙伴要疑惑了都是Bean,但是此Bean非彼Bean。今天带着小伙伴从源码的角度来分析下FactoryBean,重点是getObjectForBeanInstance方法的分析。

    前世

    在前面说到FactoryBean的前世是一个Bean,是指是一个FactoryBean的实例。先来看下getObjectForBeanInstance方法,

    /**
         * Get the object for the given bean instance, either the bean
         * instance itself or its created object in case of a FactoryBean.
         */
        protected Object getObjectForBeanInstance(
                Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    
            // Don't let calling code try to dereference the factory if the bean isn't a factory.
    //1、判断name是否以&开头 if (BeanFactoryUtils.isFactoryDereference(name)) { if (beanInstance instanceof NullBean) { return beanInstance; } if (!(beanInstance instanceof FactoryBean)) { throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass()); } } // 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.
    //beanInstance不是FactoryBean的实例或name以&开头 if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } Object object = null;
    //mbd即beanDefinition为空,从缓存中取
    if (mbd == null) { object = getCachedObjectForFactoryBean(beanName); }
    //缓存中没有,则调用FactoryBean的getObject方法,返回其对象
    if (object == null) { // Return bean instance from factory. FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // Caches object obtained from FactoryBean if it is a singleton. if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }

    看该方法上的注释,

    Get the object for the given bean instance, either the bean instance itself or its created object in case of a FactoryBean.

    用我蹩脚的英语翻译过来大概是这个意思,

    返回给定的bean Instance的一个对象,该对象可能是bean instance或者是由bean instance(是一个FactoryBean)创建的一个对象。

    意思很明白了,该方法有可能返回的是一个FactoryBean的实例,也可能是由FactroyBean生产的实例,关键看方法参数中的前两个,

    Object beanInstance  spring容器中的一个bean

    String name   可能含有&前缀的名称

    String beanName  bean的规范名称

    RootBeanDefintion mbd  BeanDefinition

    看下面的表格更容易理解该方法在各种情况下的返回值,

     

    beanInstance name 返回值
    FactoryBean的实例 带有& beanInstance
    不是FactoryBean的实例 带有& beanInstance
    FactoryBean的实例 不带& beanInstance生产的对象
    不是FactoryBean的实例 不带& beanInstance

    通过上面得表格再结合代码就很容易理解,只要是返回beanInstance对象,那么就是FactroyBean的前世,下面看FactoryBean的今生。

    今生

    这里有两个方法需要分析,分别是getCachedObjectForFactoryBean和getObjectFromFactoryBean。第一个方法是从缓存中获取,也就是说使用FactoryBean生产的bean会单独放在缓存中,非singletonObjects中,这点务必要注意

    getCachedObjectForFactoryBean

    先看下该方法的定义,

    @Nullable
        protected Object getCachedObjectForFactoryBean(String beanName) {
            return this.factoryBeanObjectCache.get(beanName);
        }

    可以看到很简单就是通过名称从factoryBeanObjectCache中取对象。factoryBeanObjectCache肯定是个map了

    /** Cache of singleton objects created by FactoryBeans: FactoryBean name to object. */
        private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);

    getObjectFromFactoryBean

    protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
            if (factory.isSingleton() && containsSingleton(beanName)) {
                synchronized (getSingletonMutex()) {
                    Object object = this.factoryBeanObjectCache.get(beanName);
                    if (object == null) {
                        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) {
                                if (isSingletonCurrentlyInCreation(beanName)) {
                                    // Temporarily return non-post-processed object, not storing it yet..
                                    return object;
                                }
                                beforeSingletonCreation(beanName);
                                try {
                                    object = postProcessObjectFromFactoryBean(object, beanName);
                                }
                                catch (Throwable ex) {
                                    throw new BeanCreationException(beanName,
                                            "Post-processing of FactoryBean's singleton object failed", ex);
                                }
                                finally {
                                    afterSingletonCreation(beanName);
                                }
                            }
    //把生产的实例对象放到factoryBeanObjectCache缓存中
    if (containsSingleton(beanName)) { this.factoryBeanObjectCache.put(beanName, object); } } } return object; } } else {
    //调用getObject方法 Object object
    = doGetObjectFromFactoryBean(factory, beanName); if (shouldPostProcess) { try { object = postProcessObjectFromFactoryBean(object, beanName); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex); } } return object; } }

    该方法就比较复杂了,主要有doGetObjectFromFactoryBean、beforeSingletonCreation、postProcessObjectFromFactoryBean、afterSingletonCreation方法,重要的一个是doGetFromFactroyBean,也就是真正干活生产bean的方法。其定义如下,其余方法可自行查看

    private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
                throws BeanCreationException {
    
            Object object;
            try {
                if (System.getSecurityManager() != null) {
                    AccessControlContext acc = getAccessControlContext();
                    try {
                        object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
                    }
                    catch (PrivilegedActionException pae) {
                        throw pae.getException();
                    }
                }
                else {
    //调用FactoryBean中的getObject方法,返回其实例对象 object
    = factory.getObject(); } } catch (FactoryBeanNotInitializedException ex) { throw new BeanCurrentlyInCreationException(beanName, ex.toString()); } catch (Throwable ex) { throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex); } // Do not accept a null value for a FactoryBean that's not fully // initialized yet: Many FactoryBeans just return null then. if (object == null) { if (isSingletonCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException( beanName, "FactoryBean which is currently in creation returned null from getObject"); } object = new NullBean(); } return object; }

    在上文中的注释部分已经看到最终调用了getObject方法,也就是返回的是FactoryBean中getObject方法的返回值。

    总结

    主要分析了FactoryBean的底层源码,判断是返回FactoryBean的实例还是返回其生产的实例,主要看bean的类型是否为FactoryBean和名称中是否带&。

    推荐:《spring中FactoryBean是什么bean

    一次性讲清楚spring中bean的生命周期之一:getSingleton方法 》

     

    bkbky