FactoryBean源码分析-28

本文详细分析了Spring中获取FactoryBean创建的bean的过程。在容器启动时,如果FactoryBean的getObjectType已知并且需要的对象存在依赖,那么在初始化阶段就会创建并缓存对象;否则,在第一次调用getBean时执行getObject方法。此外,还探讨了FactoryBean对象的缓存机制和单例行为。
摘要由CSDN通过智能技术生成

问题1:获取lubanFactoryBean里面的bean到底在哪里执行?是容器启动还是getBean的时候

 AnnotationConfigApplicationContext acx = new AnnotationConfigApplicationContext(AppConfig.class);
​
​
        //dk  factoryBean,可以看出都是同一个地址,也就是单例
        //dk在beanFactory里面的singletonObjects里面的lubanFactoryBean的值仍然为lubanFactoryBean
        //dk factoryBeanObjectCache里面存放的是FactoryBean里面的对象
        //如果FactoryBean里面的对象有注入其他的东西,则容器一旦启动,factoryBeanObjectCache会存入FactoryBean里面的对象
        System.out.println(acx.getBean("lubanFactoryBean"));
        System.out.println(acx.getBean("lubanFactoryBean"));

源码分析:

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 + "'");
                }
            }
            //dk 这行很关键
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

可以看到刚启动beanFactory里面的singletonObjects里面仍然为lubanFactoryBean

protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
​
​
        //dk 判断当前是否以&开头
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
            }
            if (mbd != null) {
                mbd.isFactoryBean = true;
            }
            return beanInstance;
        }
​
        // 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)) {
            return beanInstance;
        }
​
        Object object = null;
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        else {
            object = getCachedObjectForFactoryBean(beanName);
        }
        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());
            //dk 这行很关键,从单例池获取对象
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }
​

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        if (factory.isSingleton() && containsSingleton(beanName)) {
            synchronized (getSingletonMutex()) {
            //dk factoryBeanObjectCache里面什么也没有,所以第一次拿不到
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {
                //dk 从单例池里面获取对象,详见下文
                    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;
                    }

private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, 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 {
            //dk 调用lubanFactoryBean里面的getObject()方法,就这样拿到了对象,原路逆序返回
                object = factory.getObject();
            }
        }

//dk 如果第二次在调用则从factoryBeanObjectCache里面获取,不需要重复执行

第二种情况

假如getObject()里面的这个对象被其他的bean注入,则会在启动时候根据getObjectType来判断,并把该对象注入到容器中,也就是一启动factoryBeanObjectCache就会有一个值

@Component
public class LubanFactoryBean  implements FactoryBean {
    @Override
    public Object getObject() throws Exception {
        return new Person();
    }
​
    @Override
    public Class<?> getObjectType() {
        return Person.class;
    }
}

public class Person {
​
}

@Service(value = "u1")
//dk 注意这里如果没有value=u1的话则默认为user1,和AppConfig里面的配置冲突,直接报错
public class User1 {
​
    public  void test(){
        System.out.println("test1");
    }
​
    @Autowired
    private Person person;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值