Spring源码解析系列(6)之BeanFactory与FactoryBean的区别

BeanFactory 是接口,可以理解为bean工厂(ioc容器),用来生产和管理bean的整个生命周期

FactoryBean也是接口,可以理解为工厂bean,既然是bean,也要交由BeanFactory进行管理的,但是与普通bean不同,它可以生产对象,经过装饰之后将对象也交由BeanFactory管理(比如返回某个对象的代理对象,Mybatis继集成spring就是这样做的),我们通过FactoryBean的beanName去获取Bean时,获取到的是它的getObject()方法返回的对象,只有在beanName前面加上&符号,才能获取到真正的factoryBean对象。

BeanFactory 可以生产bean

FactoryBean只会返回普通的对象交由spring管理,而不是真正意义上的bean,他并没有经过完整的bean的生命周期

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyApplicationContextConfig.class);
User user = (User)context.getBean("userFactoryBean");
FactoryBean factoryBean = (FactoryBean) context.getBean("&userFactoryBean");
System.out.println(factoryBean);
System.out.println(user);AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyApplicationContextConfig.class);
User user = (User)context.getBean("userFactoryBean");
FactoryBean factoryBean = (FactoryBean) context.getBean("&userFactoryBean");
System.out.println(factoryBean);
System.out.println(user);

 源码剖析:

首先明确,在生成bean的beanDefinition时,是不会判断是否为FactoryBean,会像普通的bean一样,将其放入beanDefinitionMap中

public void preInstantiateSingletons() throws BeansException {
 ......
 // 如果是工厂bean在实例化时,会在beanName前面加上&,再去执行getBean()方法,但是在getBean()方法中,经过转化,还是会去掉&,按正常流程生成bean,放入singletonObjects中,也就是说beanFactory在单例池中还是以(beanName,BeanFactory类型)存在的
 if (this.isFactoryBean(beanName)) {
        bean = this.getBean("&" + beanName);
        break;
    }

    this.getBean(beanName);
    ....
}

当我们手动的调用getBean(xxx)方法时,会进入如下代码:

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
    // 进行名称的转换,如果传入的xxx是以&开头的,会返回去掉了&的beanName,如果不是直接返回。
    String beanName = this.transformedBeanName(name);
    // 从单例池中获取beanName对应的bean,根据前面的创建原则我们可以知道,如果获取的是FactoryBean,那么此处返回的就是FactoryBean本身
    Object sharedInstance = this.getSingleton(beanName);
    Object beanInstance;
    // sharedInstance从单例池中获取到了bean不为null,args默认就是null,除非我们手动传参,进入判断
    if (sharedInstance != null && args == null) {
        if (this.logger.isTraceEnabled()) {
            if (this.isSingletonCurrentlyInCreation(beanName)) {
                this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
            } else {
                this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
	// 此处就是判断获取到的bean是不是FactoryBean并且name是不是以&开头
   // 1.如果不是FactoryBean或者是FactoryBean且beanName以&开头(想要获取FactoryBean本身),直接返回原sharedInstance
   //2.如果是FactoryBean且不是以&开头(表明想要获取FactoryBean所包裹的对象),会调用它的getObject()方法,获取方法返回的对象,并返回
        beanInstance = 
            this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
    } else {
       				 ......
       // 在bean还未被创建时会进入此else中,也就是刚开始创建bean
            if (mbd.isSingleton()) {
         // FactoryBean也按照普通bean的创建方式在此处创建
                sharedInstance = this.getSingleton(beanName, () -> {
                    try {
                        return this.createBean(beanName, mbd, args);
                    } catch (BeansException var5) {
                        this.destroySingleton(beanName);
                        throw var5;
                    }
                });
           // 此处与上面相同↑,但是如果是工厂bean,在此方法中会直接将工厂bean返回
                beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }else if{
                ......   
            }else{
                ......
            }
    }

getObjectForBeanInstance()

protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    // 判断name是不是以&开头的,如果是进入if
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
            // 判断从单例池中拿到的bean是不是FactoryBean类型的,如果不是抛出异常,也就是说如果你想获取一个普通bean,但是你在它的名字前面加上了&,在获取时就会报错,抛出BeanIsNotAFactoryException异常
        } else if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
        } else {
            if (mbd != null) {
            // 经过上述判断,来到此处,将其标志为工厂Bean
                mbd.isFactoryBean = true;
            }
			// 到这里,就可以知道它是一个工厂bean,并且name以&开头,想要获取工厂bean本身,直接返回原bean即可
            return beanInstance;
        }
        // 如果不是工厂bean,直接返回原bean
    } else if (!(beanInstance instanceof FactoryBean)) {
        return beanInstance;
    } else {
        // 如果是工厂bean,但是不是以&开头的,所以会去获取getObject()所返回的对象
        Object object = null;
        if (mbd != null) {
            mbd.isFactoryBean = true;
        } else {
            object = this.getCachedObjectForFactoryBean(beanName);
        }

        if (object == null) {
            FactoryBean<?> factory = (FactoryBean)beanInstance;
            if (mbd == null && this.containsBeanDefinition(beanName)) {
                mbd = this.getMergedLocalBeanDefinition(beanName);
            }
		// 判断beanDefinition是不是合成的,一般情况下由spring容器产生的beanDefinition都不是合成的
            boolean synthetic = mbd != null && mbd.isSynthetic();
        // 调用FactoryBean的getObject()方法,获取其返回的对象
            object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
        }

        return object;
    }
}

getObjectFromFactoryBean()

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    if (factory.isSingleton() && this.containsSingleton(beanName)) {
        synchronized(this.getSingletonMutex()) {
   //从FactoryBean对象的缓存池中获取,因为是首次获取,肯定是获取不到的
   // Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap(16);
            Object object = this.factoryBeanObjectCache.get(beanName);
            if (object == null) {
       // 调用FactoryBean的getObject()方法,获取对象
                object = this.doGetObjectFromFactoryBean(factory, beanName);
       // 再次尝试从缓存池中获取
                Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                if (alreadyThere != null) {
            // 如果缓存池中存在了,直接更新objects为缓存池中的值
                    object = alreadyThere;
                } else {
           // 此处判断需不需要对该对象进行后置处理(比如对其进行aop增强)
           // shouldPostProcess = !synthetic,只要beanDefinition不是合成的,就需要进行后置处理
                    if (shouldPostProcess) {
                        if (this.isSingletonCurrentlyInCreation(beanName)) {
                            return object;
                        }
		// 将该工厂bean声明为正在创建状态
                        this.beforeSingletonCreation(beanName);

                        try {
        // 调用BeanPostProcessor后置处理器的postProcessAfterInitialization方法,如果FactoryBean进行了Aop代理增强,那么也需要对object进行aop增强
                            object = this.postProcessObjectFromFactoryBean(object, beanName);
                        } catch (Throwable var14) {
                            throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", var14);
                        } finally {
                            this.afterSingletonCreation(beanName);
                        }
                    }

                    if (this.containsSingleton(beanName)) {
                 // 将getObject()获取到的对象放入factoryBean的对象缓存池中,下次直接从缓存池中获取
                       this.factoryBeanObjectCache.put(beanName, object);
                    }
                }
            }

            return object;
        }
    } else {
        Object object = this.doGetObjectFromFactoryBean(factory, beanName);
        if (shouldPostProcess) {
            try {
                object = this.postProcessObjectFromFactoryBean(object, beanName);
            } catch (Throwable var17) {
                throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", var17);
            }
        }

        return object;
    }
}

doGetObjectFromFactoryBean()

private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
    Object object;
    try {
        // 系统的安全管理员默认是null
        if (System.getSecurityManager() != null) {
            AccessControlContext acc = this.getAccessControlContext();

            try {
                object = AccessController.doPrivileged(factory::getObject, acc);
            } catch (PrivilegedActionException var6) {
                throw var6.getException();
            }
        } else {
            // 调用其getObject()方法,获取对象
            object = factory.getObject();
        }
    } catch (FactoryBeanNotInitializedException var7) {
        throw new BeanCurrentlyInCreationException(beanName, var7.toString());
    } catch (Throwable var8) {
        throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", var8);
    }

    if (object == null) {
        if (this.isSingletonCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");
        }
		// 如果object是null,并且当前工厂对象没有处于正在创建的状态,就返回NullBean对象
        object = new NullBean();
    }
	// 将object返回
    return object;
}

总结:

1.FactoryBean包裹的对象是天然懒加载的,如果FactoryBean是单例的,则会在第一个调用getBean()的时候创建,然后放到factoryBeanObjectCache缓存中,并且FactoryBean在单例池中就是以beanName,bean的形式存在的,并不会加上&,只有在getBean(“xxx”),才会根据传入的beanName去进行判断,从不同的地方获取

2.我们在写AOP增强的时候,不只是会增强FactoryBean本身,还会增强FactoryBean所包裹的对象

如有问题欢迎指正讨论......

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值