Spring容器启动流程(下)

一般来说,Spring框架启动流程大体上分成两个大的步骤:IoC容器初始化和Bean的依赖注入。

Bean的依赖注入

Bean的依赖注入大致可分为如下过程:

  • 转换对应beanName;

  • 尝试从缓存中加载单例;

  • 获取单例

  • 创建Bean

转换对应beanName

考虑到传入的beanName可能是别名,也有可能是FactoryBean,因此需要进行必要的转换。简单来说,如果是FactoryBean的话,去除前面的修饰符“&”;如果是alias,取指定alias所表示的最终beanName。

尝试从缓存中加载单例

Spring框架中尝试加载单例的代码如下:

public Object getSingleton(String beanName) {
        return this.getSingleton(beanName, true);
    }

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            Map var4 = this.singletonObjects;
            synchronized(this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
  • 代码中涉及到三个map类型的对象:singletonObjects、earlySingletonObjects、singletonFactories;
  • 从代码逻辑中可以看到,首先尝试从singletonObjects中加载;
  • 如果获取不到,再从earlySingletonObjects中获取;
  • 如果再获取不到,则尝试从singletonFactories里面获取beanName对应得ObjectFactory;
  • 然后调用这个ObjectFactory的getObject方法来创建bean,并放到earlySingletonObjects里面去;
  • 然后从singletonFactories删除对应的ObjectFactory。

在得到bean的实例后需要调用getObjectForBeanInstance方法来检测一下正确性,其实就是检测当前bean是否为FactoryBean类型的bean,如果是,需要调用对应的getObject方法作为返回值。

protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
        if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(this.transformedBeanName(name), beanInstance.getClass());
        } else if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
            Object object = null;
            if (mbd == null) {
                object = this.getCachedObjectForFactoryBean(beanName);
            }

            if (object == null) {
                FactoryBean<?> factory = (FactoryBean)beanInstance;
                if (mbd == null && this.containsBeanDefinition(beanName)) {
                    mbd = this.getMergedLocalBeanDefinition(beanName);
                }

                boolean synthetic = mbd != null && mbd.isSynthetic();
                object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
            }

            return object;
        } else {
            return beanInstance;
        }
    }

上述代码中对于非FactoryBean不做任何处理,而将从Factory中解析bean的工作委托给了getObjectFromFactoryBean方法。

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        if (factory.isSingleton() && this.containsSingleton(beanName)) {
            synchronized(this.getSingletonMutex()) {
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {
                    object = this.doGetObjectFromFactoryBean(factory, beanName);
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    if (alreadyThere != null) {
                        object = alreadyThere;
                    } else {
                        if (object != null && shouldPostProcess) {
                            try {
                                object = this.postProcessObjectFromFactoryBean(object, beanName);
                            } catch (Throwable var9) {
                                throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", var9);
                            }
                        }

                        this.factoryBeanObjectCache.put(beanName, object != null ? object : NULL_OBJECT);
                    }
                }

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

            return object;
        }
    }

代码中只有一处需要注意的,那就是如果bean是单例的,那就要保证全局唯一,也因为是单例,可以不必重复创建,使用缓存来提高性能。最后去调用doGetObjectFromFactoryBean方法。

private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, String beanName) throws BeanCreationException {
        Object object;
        try {
            if (System.getSecurityManager() != null) {
                AccessControlContext acc = this.getAccessControlContext();

                try {
                    object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        public Object run() throws Exception {
                            return factory.getObject();
                        }
                    }, acc);
                } catch (PrivilegedActionException var6) {
                    throw var6.getException();
                }
            } else {
                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 && this.isSingletonCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");
        } else {
            return object;
        }
    }

可以看到,通过直接调用getObject方法获取bean,并通过postProcessObjectFromFactoryBean方法完成相应的后处理。Spring获取bean的规则中有一条:尽可能保证所有bean初始化后都会调用注册的BeanPostProcessor的postProcessAfterInitialization方法进行处理。

获取单例

如果当前缓存中不存在对应的单例Bean,那就必须从头开始加载Bean,ObjectFactory的核心部分就是调用createBean方法。

sharedInstance = this.getSingleton(beanName, new ObjectFactory() {
                    public Object getObject() throws BeansException {
                        try {
                            return AbstractBeanFactory.this.createBean(beanName, mbd, args);
                        } catch (BeansException var2) {
                            AbstractBeanFactory.this.destroySingleton(beanName);
                            throw var2;
                        }
                    }
                });
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Creating instance of bean '" + beanName + "'");
        }

        this.resolveBeanClass(mbd, beanName, new Class[0]);

        try {
            mbd.prepareMethodOverrides();
        } catch (BeanDefinitionValidationException var5) {
            throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "Validation of method overrides failed", var5);
        }

        Object beanInstance;
        try {
            beanInstance = this.resolveBeforeInstantiation(beanName, mbd);
            if (beanInstance != null) {
                return beanInstance;
            }
        } catch (Throwable var6) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var6);
        }

        beanInstance = this.doCreateBean(beanName, mbd, args);
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Finished creating instance of bean '" + beanName + "'");
        }

        return beanInstance;
    }

在调用doCreateBean方法之前,先调用了prepareMethodOverrides和resolveBeforeInstantiation两个方法,前者完成override属性处理,后者完成bean实例化的前置处理,此处暂不叙述,读者可关注后续文章。

创建Bean

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            //如果是单例则需要首先清除缓存
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }

        if (instanceWrapper == null) {
            //根据指定bean使用对应的策略创建新的实例
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }

        final Object bean = instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null;
        Class<?> beanType = instanceWrapper != null ? instanceWrapper.getWrappedClass() : null;
        Object var7 = mbd.postProcessingLock;
        synchronized(mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                mbd.postProcessed = true;
            }
        }

        //如果是单例并且允许循环依赖并且当前bean正在创建中检测到循环依赖,则需要提早曝光
        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }

            this.addSingletonFactory(beanName, new ObjectFactory<Object>() {
                public Object getObject() throws BeansException {
                    return AbstractAutowireCapableBeanFactory.this.getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

        Object exposedObject = bean;

        try {
            //填充bean,注入属性值,如果存在依赖其他bean的属性,递归初始化所依赖的bean
            this.populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                exposedObject = this.initializeBean(beanName, exposedObject, mbd);
            }
        } catch (Throwable var17) {
            if (var17 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var17).getBeanName())) {
                throw (BeanCreationException)var17;
            }

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var17);
        }

        if (earlySingletonExposure) {
            Object earlySingletonReference = this.getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                    String[] dependentBeans = this.getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                    String[] arr$ = dependentBeans;
                    int len$ = dependentBeans.length;

                    for(int i$ = 0; i$ < len$; ++i$) {
                        String dependentBean = arr$[i$];
                        if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                            actualDependentBeans.add(dependentBean);
                        }
                    }

                    if (!actualDependentBeans.isEmpty()) {
                        throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                    }
                }
            }
        }

        try {
            //根据scope注册bean
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
        }
    }
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
        Class<?> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
        if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
        } else if (mbd.getFactoryMethodName() != null) {
            //如果工厂方法不为空则使用工厂方法初始化策略
            return this.instantiateUsingFactoryMethod(beanName, mbd, args);
        } else {
            boolean resolved = false;
            boolean autowireNecessary = false;
            if (args == null) {
                Object var7 = mbd.constructorArgumentLock;
                synchronized(mbd.constructorArgumentLock) {
                    //根据参数确定调用的构造方法或者工厂方法
                    if (mbd.resolvedConstructorOrFactoryMethod != null) {
                        resolved = true;
                        autowireNecessary = mbd.constructorArgumentsResolved;
                    }
                }
            }

            if (resolved) {
                //确定使用构造方法自动注入还是使用默认构造方法构造
                return autowireNecessary ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) : this.instantiateBean(beanName, mbd);
            } else {
                Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
                //确定使用构造方法自动注入还是使用默认构造方法构造
                return ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args) ? this.instantiateBean(beanName, mbd) : this.autowireConstructor(beanName, mbd, ctors, args);
            }
        }
    }

从代码中可以看出,Spring通过autowireConstructor和instantiateBean两个方法创建Bean实例。前者逻辑复杂,代码量巨大,但从其功能实现的角度考虑了如下几个方面:

  • 构造函数参数的确定(隐式参数、缓存、配置文件);

  • 构造函数的确定;

  • 根据确定的构造函数转换对应的参数类型;

  • 构造函数不确定性的验证;

  • 根据实例化策略以及得到的构造函数寄构造函数参数实例化Bean。

后者逻辑简单,由于不需要考虑参数,因此直接调用实例化策略进行实例化就可以了。实例化操作结束后,需要注入属性。重点是
autowireByName和autowireByType两个方法。

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
        PropertyValues pvs = mbd.getPropertyValues();
        if (bw == null) {
            if (!((PropertyValues)pvs).isEmpty()) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
        } else {
            boolean continueWithPropertyPopulation = true;
            if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
                Iterator i$ = this.getBeanPostProcessors().iterator();

                while(i$.hasNext()) {
                    BeanPostProcessor bp = (BeanPostProcessor)i$.next();
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                        if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                            continueWithPropertyPopulation = false;
                            break;
                        }
                    }
                }
            }

            if (continueWithPropertyPopulation) {
                if (mbd.getResolvedAutowireMode() == 1 || mbd.getResolvedAutowireMode() == 2) {
                    MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
                    if (mbd.getResolvedAutowireMode() == 1) {
                        this.autowireByName(beanName, mbd, bw, newPvs);
                    }

                    if (mbd.getResolvedAutowireMode() == 2) {
                        this.autowireByType(beanName, mbd, bw, newPvs);
                    }

                    pvs = newPvs;
                }

                boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
                boolean needsDepCheck = mbd.getDependencyCheck() != 0;
                if (hasInstAwareBpps || needsDepCheck) {
                    PropertyDescriptor[] filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                    if (hasInstAwareBpps) {
                        Iterator i$ = this.getBeanPostProcessors().iterator();

                        while(i$.hasNext()) {
                            BeanPostProcessor bp = (BeanPostProcessor)i$.next();
                            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                                pvs = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
                                if (pvs == null) {
                                    return;
                                }
                            }
                        }
                    }

                    if (needsDepCheck) {
                        this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
                    }
                }

                this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
            }
        }
    }

此时Spring已经完成了bean的实例化和属性的填充,接着便会调用用户设定的初始化方法。一般而言,用户可以有三种途径自定义初始化方法,后续文章会有详细叙述,敬请关注。

总结

笔者花了两篇博文的篇幅大致介绍了Spring容器的启动过程,还有很多细节方面并未涉及,例如循环依赖、具体属性值注入等。平时开发时对于容器启动时打印的日志信息毫无感觉,现在读者可以结合博文再去关注日志信息,相信会有更深的体会。祝好!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值