2、Spring源码之FactoryBean

本文解析了FactoryBean与BeanFactory的区别及应用场景。FactoryBean通过getObject方法提供更灵活的对象创建方式,而BeanFactory负责管理整个创建流程。文章还介绍了如何在Spring容器中获取这两种对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 先抛出面试经常问的问题 FactoryBean  和 BeanFactory的区别?
    相同点:都是用来创建对象的。
    不同点:
    ①当使用BeanFactory的时候必须要遵循完整的创建过程,这个过程是由spring来管理控制的。
    ②而使用FactoryBean只需要调用getObject就可以返回具体的对象,整个对象的创建过程是由用户自己来控制的,更加灵活
    ③FactoryBean对象和FactoryBean的getObject创建出来的对象都交到BeanFactory管理
  2. spring在管理FactoryBean实际上是管理了几个对象?
    实际上是两个对象 
    其中FactoryBean的getObject 方法创建的对象是放factoryBeanObjectCache里面的
  3. 代码示例:
    package com.zhangfuyin.factoryBean;
    
    import org.springframework.beans.factory.FactoryBean;
    import org.springframework.stereotype.Component;
    
    /**
     * @author lenovo
     */
    @Component
    public class MyFactoryBean implements FactoryBean<BeanObj> {
    
    
    	@Override
    	public BeanObj getObject() throws Exception {
    		return new BeanObj();
    	}
    
    	@Override
    	public Class<?> getObjectType() {
    		return BeanObj.class;
    	}
    
    	@Override
    	public boolean isSingleton() {
    		return true;
    	}
    }
    

  4. 如何从spring容器中获取FactoryBean的getObject对象?如何从或FactoryBean对象呢?
    获取getObject对象:
    Object factoryBeanObj = ac.getBean("myFactoryBean");

    获取FactoryBean对象通过取地址符(后面源码分析都会看到具体源码):
    MyFactoryBean factoryBean = (MyFactoryBean)ac.getBean("&myFactoryBean");

     
  5. 在spring容器中BeanDefinition存储的FactoryBean的bean定义信息
     
    for (String beanName : beanNames) {
    			// 合并的bd实际上就是RootBeanDefinition,在Spring中没有MergedBeanDefinition类,而有MergedBeanDefinitionPostProcessor
    			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    			// 如果不是抽象的、是单例且不是懒加载的
    			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    				if (isFactoryBean(beanName)) {
    					// 如果bean是FactoryBean类型,则需要获取原来的bean对象,需要在beanName前加一个"&"符号
    					Object bean = 	getBean(FACTORY_BEAN_PREFIX + beanName);
    					if (bean instanceof FactoryBean) {
    						final FactoryBean<?> factory = (FactoryBean<?>) bean;
    						boolean isEagerInit;
    						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
    							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
    											((SmartFactoryBean<?>) factory)::isEagerInit,
    									getAccessControlContext());
    						}
    						else {
    							isEagerInit = (factory instanceof SmartFactoryBean &&
    									((SmartFactoryBean<?>) factory).isEagerInit());
    						}
    						if (isEagerInit) {
    							getBean(beanName);
    						}
    					}
    				}
    				else {
    					// 如果bean不是FactoryBean类型,直接调用getBean去创建bean(大多数场景都会直接进到这个else代码块)
    					getBean(beanName);
    				}
    			}
    		}

    这里如果bean的定义信息是FactoryBean的时候 加上"&"取地址符去创建信息

  6. 创建FactoryBean对象  这里不在详细说明  主要看doCreateBean方法、最终FactoryBean对象会被放到一级缓存里面去
     
  7. 如何获取FacoryBean对象和FactoryBean创建得对象和普通Bean对象
    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);
    							}
    						}
    						if (containsSingleton(beanName)) {
    							this.factoryBeanObjectCache.put(beanName, object);
    						}
    					}
    				}
    				return object;
    			}
    		}
    		else {
    			// 这里的方法很关键,看见do打头的就知道是真正干活的,下面就是要通过factoryBean定制化beanName对应的实例
    			Object object = doGetObjectFromFactoryBean(factory, beanName);
    			if (shouldPostProcess) {
    				try {
    					// 由于object是走的是FactoryBean的定制方法
    					// 因此postProcessBeforeInitialization的方法是不会被调用了
    					// 但是postProcessAfterInitialization方法会被调用,也就是bean初始化后做一些事情
    					object = postProcessObjectFromFactoryBean(object, beanName);
    				}
    				catch (Throwable ex) {
    					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
    				}
    			}
    			return object;
    		}
    	}


    ①如果要取得对象名称有“&”取地址符 直接把普通缓存的FactoryBean对象返回
    ②如果没有取地址符 如果不是FactoryBean类型 那么就是普通对象 直接返回普通对象
    ③如果factoryBeanObjectCache有对象 那么将返回 否则调用FactoryBeanFactoy.getObject
    返回对象返回、并且放入factoryBeanObjectCache中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值