spring非懒加载的bean实例化源码分析

懒加载和非懒加载

懒加载指的是spring容器初始化的时候并不实例,当用到的时候才实例化,需要在标签上指定”lazy-init”属性值为true,用到的时候不只是直接使用,或者是被别的非懒加载bean依赖了。

非赖加载指的是spring容器初始化的时候实例化bean,bean不限制是单例(singleton)还是多例(prototype)但是都只实例一个bean,一般bean都是非懒加载,除非bean比较耗资源。

既然了解到什么是非懒加载的bean就知道这类bean是在初始化spring容器的时候初始化的,那么延续上篇文章继续读源码。

refresh()之finishBeanFactoryInitialization()

AbstractApplicationContext的refresh()里面的this.finishBeanFactoryInitialization(beanFactory),我们来读读

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        if(beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
            beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
        }

        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        String[] var3 = weaverAwareNames;
        int var4 = weaverAwareNames.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String weaverAwareName = var3[var5];
            this.getBean(weaverAwareName);
        }

        beanFactory.setTempClassLoader((ClassLoader)null);
        beanFactory.freezeConfiguration();
        beanFactory.preInstantiateSingletons();
    }
    public void freezeConfiguration() {
        this.configurationFrozen = true;
        this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
    }

先判断beanFactory里面是否有类型转换服务bean有就设置转换服务;然后给beanFactory设置一个null临时类加载器-停止使用用于类型匹配的临时类加载器;然后把非懒bean的名字赋值给frozenBeanDefinitionNames,冻结所有的bean定义,表明已注册的bean定义将不会被修改或后处理。

下面一个方法是真正的主角beanFactory.preInstantiateSingletons();,实例全部剩余非懒加载单例bean

finishBeanFactoryInitialization()之preInstantiateSingletons()

class  DefaaultListableBeanFactory...
public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Pre-instantiating singletons in " + this);
        }

        // Iterate over a copy to allow for init methods which in turn register new bean definitions.
        // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
        List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

        // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                if (isFactoryBean(beanName)) {
                    final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                            @Override
                            public Boolean run() {
                                return ((SmartFactoryBean<?>) factory).isEagerInit();
                            }
                        }, getAccessControlContext());
                    }
                    else {
                        isEagerInit = (factory instanceof SmartFactoryBean &&
                                ((SmartFactoryBean<?>) factory).isEagerInit());
                    }
                    if (isEagerInit) {
                        getBean(beanName);
                    }
                }
                else {
                    getBean(beanName);
                }
            }
        }

        // Trigger post-initialization callback for all applicable beans...
        for (String beanName : beanNames) {
            Object singletonInstance = getSingleton(beanName);
            if (singletonInstance instanceof SmartInitializingSingleton) {
                final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged(new PrivilegedAction<Object>() {
                        @Override
                        public Object run() {
                            smartSingleton.afterSingletonsInstantiated();
                            return null;
                        }
                    }, getAccessControlContext());
                }
                else {
                    smartSingleton.afterSingletonsInstantiated();
                }
            }
        }
    }

迭代一个beanNames副本为了给init方法用,该方法依次注册新的bean定义。beanNames有值就根据beanName获得RootBeanDefinition,这个Rootbean定义表示合并的bean定义,在spring beanFactory运行时返回一个特定的bean。它可能是由多个相互继承的原始bean定义创建的。一个RootBean本质上是统一的bean定义视图;如果是抽象的、不是单例的、是懒加载的就继续判断是否是工厂bean,不是的话就进入this.getBean(beanName);,由于还没初始化所以工厂bean里面根本就存在所以直接执行this.getBean(beanName);

preInstantiateSingletons()之this.getBean(beanName)

这个getBean最终调用的是AbstractBeanFactory的doGetBean(),代码很长,我们慢慢读。

 protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
        final String beanName = this.transformedBeanName(name);
        Object sharedInstance = this.getSingleton(beanName);
        Object bean;
        if(sharedInstance != null && args == null) {
            if(this.logger.isDebugEnabled()) {
                if(this.isSingletonCurrentlyInCreation(beanName)) {
                    this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
                } else {
                    this.logger.debug(
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值