Spring Bean实例化过程(1)

本文详细探讨了Spring容器中Bean的实例化过程,包括在`AbstractApplicationContext.refresh()`时开始的预实例化,以及如何在`DefaultListableBeanFactory.preInstantiateSingletons()`中按顺序实例化Bean。BeanDefinition的合并与缓存、抽象Bean、单例Bean和FactoryBean的处理等关键步骤被逐一剖析,特别强调了SmartFactoryBean在实例化过程中的特殊角色。

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

Spring容器启动和初始化过程实际上可以分为两个阶段,第一个阶段是容器的初始化,包括容器的创建,bean配置文件读取,解析和BeanDefinition的生成及注册。第二个阶段是bean的实例化,从beanDefinition到bean实例的生成,包括aop的切入等。

ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
concurrentTemplate = (AbstractConcurrentTemplate) context.getBean("tairConcurrentTemplate");
上面简单两行,已经包括了Spring的初始化和实例化过程。


Spring中Bean的实例化的触发时机包括主要两类,一步是在初始化结束后,一个是getBean触发时。

bean的实例化过程实际上在AbstractApplicationContext.refresh()时就开始了,具体的入口为:refresh->finishBeanFactoryInitialization->beanFactory.preInstantiateSingletons(),preInstantiateSingletons的实现在DefaultListableBeanFactory类中。

DefaultListableBeanFactory中preInstantiateSingletons的具体逻辑为:

public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isInfoEnabled()) {
            this.logger.info("Pre-instantiating singletons in " + this);
        }
 
        synchronized (this.beanDefinitionMap) {
            for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext();) {
                String beanName = (String) it.next();
                RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                    if (isFactoryBean(beanName)) {
                        FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
                        if (factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit()) {
                            getBean(beanName);
                        }
                    }
                    else {
                        getBean(beanName);
                    }
                }
            }
        }
    }

遍历beanDefinitionNames链表,这里面按照注册顺序保存了bean的名字

1. AbstractBeanFactory.getMergedLocalBeanDefinition,根据bean名字获取merge后的BeanDefinition,这里merge的内容包括:parent Bean的内容,该方法的具体逻辑是:

1.1 先从mergeBeanDefinition缓存中取,如果能取到,说明前面已经merge过,无须再merge,直接返回。

1.2 根据bean的配置信息,若该bean,指定了parent参数,则获取parentName。

若parentName和当前beanName相同,则直接在父容器中获取parentBean对应的mergeBeanDefinition。否则判断当前容器中是否有parentName对应的bean存在,有则从当前容器中取得parentBeanName的mergeBeanDefinition,否则也从父容器中获取。这里实际上是递归调用,如果最终都无法找到,那么只能报错了。这里的merge实际上是深度拷贝,先拷贝parentBean的mergeBeanDefinition,然后再用当前bean中定义的属性覆盖掉部分属性(overrideFrom)。

1.3 获取beanDefinition后,将其缓存起来,便于后面直接从缓存中获取。

2. 获取得到beanDefinition之后,判断当前bean是否满足:非abstract,isSingleton,且没有指定lazyInit,若不满足,则跳过实例化。

3. 判断当前bean是否是FactoryBean,若是,则3.1,否则3.2

3.1 对于FactoryBean,现在bean前面加上&号,实例化FactoryBean。若是SmartFactoryBean,且isEgerInit(),则实例化由该factoryBean生成的bean。

从这里可以知道:

对于singleton域的FactoryBean(非SmartFactoryBean)类型的bean,在初始化结束后只会实例化工厂bean自身。为了满足一些特殊情况,spring中提供了SmartFactoryBean接口。

3.2 对于普通bean,直接实例化。

从上面可以看到,实例化的方法的真正入口还是getBean。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值