Spring源码解析(二)

Bean的加载

spring的bean的加载是一个复杂的过程,本文旨在从大局上看spring到底在加载时做了些什么,然后再进行细节分析。

首先,在看源码之前要先去阅读几个关键的类,来帮助阅读

1:BeanWrapper,这个接口都有些什么功能呢,我们从他的uml图中看一下。
BeanWrapper的UML
主要实现了3个功能

  • 1.属性的访问和存储
  • 2.属性编辑器注册表
  • 3.类型转换

这个接口的实现类很朴实,主要的目的就是通过反射来读写属性,我们通常理解的Bean的生成是直接知道了class然后通过forname反射出来的bean,但这种方法相当于将代码写死了,beanWrapper是根据配置文件来动态生成的,他每一个属性都是通过TypeConvert进行转换然后反射出来,形成了一个beanwrapper,这个beanWrapper和你生命的bean的属性类型都是一模一样的,所以这就是我们得到的bean。读写beanWrapper的property的方法源码如下,感兴趣的同学可以再深入研究下。

@Override
        @Nullable
        public Object getValue() throws Exception {
            final Method readMethod = this.pd.getReadMethod();
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    ReflectionUtils.makeAccessible(readMethod);
                    return null;
                });
                try {
                    return AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
                            readMethod.invoke(getWrappedInstance(), (Object[]) null), acc);
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                ReflectionUtils.makeAccessible(readMethod);
                return readMethod.invoke(getWrappedInstance(), (Object[]) null);
            }
        }

        @Override
        public void setValue(final @Nullable Object value) throws Exception {
            final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
                    ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
                    this.pd.getWriteMethod());
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    ReflectionUtils.makeAccessible(writeMethod);
                    return null;
                });
                try {
                    AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () ->
                            writeMethod.invoke(getWrappedInstance(), value), acc);
                }
                catch (PrivilegedActionException ex) {
                    throw ex.getException();
                }
            }
            else {
                ReflectionUtils.makeAccessible(writeMethod);
                writeMethod.invoke(getWrappedInstance(), value);
            }
        }
    }

2:我们要了解的是AccesssController,这个是和权限有关的了,要知道,除了native代码,其他代码都是有自己的域的,还有一部分外来代码以前是在沙箱中的,这使得代码运行的权限是不一样的,而AccessController就是用来判断权限并授权的,具体的判断机制就不详细说了,因为这不是重点,你所需要知道的只有两个方法

  • 1:checkPermission(Permission perm)

    Perm你可以理解为一个权限map,然后checkPermission就是如其名,检查这个映射是否符合规则,如果符合,就进行授权。

  • 2:doPrivileged(PrivilegedAction action);

    这个方法就牛逼了啊,临时授权!就是在这个方法内执行的东西,拥有所有权限,比如我们底层的反射,首先要开通反射权限,然后要开通反射方法执行权限。在上面set源码中有很好的体现。有了这些基础知识,你可以开心的进入bean的加载了。

3:BeanFactory和FactoryBean
我最开始看到这两个东西时候的想法是,是不是写错了,后来……

没错,这TMD就是两个东西。下面来说明一下他俩的关系。

BeanFactory就是spring最关键的最核心的一个类,我记得有人这样比喻IOC,很形象,Bean的Instance就是球,Bean就是造球的模具,IOC是一个盒子,BeanFactory就是造造球模具的工具,而FactoryBean是一个特殊的造球的模具,特殊的Bean,因为他实现了FactoryBean<T>。我们通常从bean中得到的本应该是bean,但是FactoryBean得到的却是getObject(无参,具体逻辑子类实现)方法中的bean。

而我们说的beanFactory的作用就是实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。他是SpringIOC的核心接口。

而我们获取bean的方法就是BeanFactory的getObject(有参,类的名字之类的);中二点的话你可以理解为万物起源。

spring程序员的编码风格

1:单一职责,大部分的类都只完成自己的工作,很少有身兼两职的,
2:大部分的方法中只完成大框逻辑,而细节由另一个方法进行封装。
3:看似是执行逻辑的create……(),resolve……()方法实际上是进行前戏准备,而真正核心的逻辑由do……()开头的方法执行,没错,到这里你就该提起精神了。

阅读源码之大局观

准备工作大致说完了,我们来看一下spring加载bean的时候,从大局观上看,他都做了些什么。
时序图这种东西,我画起来太丑了,就不画了,我就分条解说吧。
1:AbstarctBeanFactory的getBean()中的doGetBean(),

  • 获取Bean真正的名字
  • 从缓存中取bean
  • 如果取到了,判断是不是FactoryBean,是就getObject(),不是就直接返回
  • 如果没取到就进行下一步
  • 检查这个BeanFactory中是否有BeanDefinition,如果没有就去查他的父类
  • 看看是不是只是检查类型,如果不是就在createBean的那个map中标记现在老子要开始创建类了。
  • 上一篇Spring源码解析(一)文章中,获取到的RootBeanDefinition有了用武之地。以下全都以mbd来表示
  • 先看看这个mbd中的dependon属性,检查一下是否有依赖的bean,有就先创建这个依赖bean。然后注册到注册表(Map)中,
  • 根据不同的域来创建bean的实例,然后检查是不是FactoryBean。
  • 最后如果需要bean的类型转换,就进行转换。

然后单说倒数第二步创建实例。

  • 以单例为例,因为是共享bean,所以首先还是先从缓存中取,有就判断,没有就继续。
  • 然后标记一下我这要开始bean创建实例啦
  • 开始创建bean中……
  • 检查mbd中是否有需要重写的方法。如果有就在重写前标记个false,重写后标记为true
  • 初始化bean的前后插入postProcessor
  • 创建个BeanWrapper,然后从缓存中取,取到返回,没取到继续。
  • 检查参数,然后选择InstantiationStrategy,
    默认是CglibSubclassingInstantiationStrategy()来初始化Bean,然后通过反射来获取bean的所有构造器,然后按照构造器参数从多到少,从public构造器到private构造器的是顺序排序,根据参数的类型,及数量来选择初始化bean的构造器。
  • 然后根据构造器,反射构造出bean。
  • mbd的判断,如果有父类,融合在父类中的属性。
  • 判断是否支持循环依赖,如果支持,就暴露beanFactory在map中。
  • 初始化bean的实例。将mbd的属性以反射形式注入生成的beanInstance;
  • 创建完成后删除开始创建bean标记

结合源码细节分析

从getBean说起

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

        // 由于我们会给bean设置一些别名方便使用,所以这一步就是要获取bean的权威的,真正的名字。
        final String beanName = transformedBeanName(name);
        Object bean;

        //从缓存map中获取单例模式的实例。
        Object sharedInstance = getSingleton(beanName);
        //如果能取到实例,且传入的参数为空。就进行验证后返回。
        if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            //检查是不是FactoryBean
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        //如果没有从缓存中拿到,就继续。
        else {

            // 判断是否已经创建这个bean,是否是在循环依赖.
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // 检查是否有beanDefinition在这个BeanFactory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // 如果没找到BeanDefinition,就去找他的父类。
                String nameToLookup = originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    //递归调用doGetBean();
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    // 委派给代参的父类。
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // 委派给无参的父类。
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }
            //如果不只是类型检查,我们以mergedBeanDefinitions作为同步锁,
            //在alreadyCreated这个Set中添加这个bean开始创建了,
            //然后从锁住的的这个Map中移除RootBeanDefinition。
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }


            try {
                //这里就不打开说了,这个方法的主要作用就是获取一个RootBeanDefinition。
                //先从mergedBeanDefinitions缓存Map获取,缓存如果没有,就根据beanName去beanDefinitionMap这个缓存中去寻找。
                //然后以mergedBeanDefinitions缓存Map为锁进行融合。
                //首先通过getParentName()检查有没有父类
                //如果有,就递归调用getMergedBeanDefinition(parentName)这个方法
                //如果没有就进行属性克隆。
                //根据Override属性进行重写
                //根据rb中读取出来的域配置来设置域属性。
                //返回mbd
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // 检查是否有依赖的bean,如果有就引入下一个栈帧,
                // 先去加载被依赖的bean,递归调用AbstractFactoryBean的getBean(String beanName);
                // 然后将依赖关系注册到依赖map中。
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        registerDependentBean(dep, beanName);
                        try {
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                //根据不同的scope策略创建实例
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    //检查是否是FactoryBean
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                else {
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }
                    try {
                        Object scopedInstance = scope.get(beanName, () -> {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        throw new BeanCreationException(beanName,
                                "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                ex);
                    }
                }
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        //检查需要的type是否是实例中创建出来的type,如果不是要进行类型转换。
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            }
            catch (TypeMismatchException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }

然后我们将根据不同的域创建实例拿出来单说
以单例为例子。

if (mbd.isSingleton()) {
                    //这个getSingleton()的参数是String类型的BeanName,
                    //ObjectFactory类型的一个匿名对象。既然是factory
                    //就会实现getBean()方法
                    //return createBean(beanName, mbd, args);就是回调的方法
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

插一句说几个map

    /** 根据beanName缓存bean真正创建的实例的map */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    /** 根据BeanName缓存bean的factory的map */
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

    /** 根据beanName缓存bean实例,这个实例与上面的实例不太一样, */
    /** 因为这个是由为了解决依赖循环提早暴露出来的factory通过getObject获取的实例,属性未经填充的 */
    /** 所以这里缓存的是为了解决依赖循环而生成的bean实例 */
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

    /** 将是单例的bean注册在这里。 */
    private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

    /** 当我们开始创建bean,就在这里标记上我这个bean已经开始创建了,防止循环依赖创建 */
    private final Set<String> singletonsCurrentlyInCreation =
            Collections.newSetFromMap(new ConcurrentHashMap<>(16));

之后,这里我们打开getSingleton()方法。

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        //惯例同步操作,以对象map为锁。
        synchronized (this.singletonObjects) {
            //惯例尝试从缓存中获取对象
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,
                            "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                            "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
                //这个方法看似只是一个判断,但是利用了&&符号的短路原理,进行了两个操作
                //1:检查inCreationCheckExclusions中是否有这个bean
                //2:在singletonsCurrentlyInCreation这个set缓存中加入了这个bean的名字。
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    //一会儿去回调方法中看。
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                catch (IllegalStateException ex) {
                    // Has the singleton object implicitly appeared in the meantime ->
                    // if yes, proceed with it since the exception indicates that state.
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw ex;
                    }
                }
                catch (BeanCreationException ex) {
                    if (recordSuppressedExceptions) {
                        for (Exception suppressedException : this.suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                    throw ex;
                }
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    //和之前的before相对应
                    //将beanname从map中移除。
                    afterSingletonCreation(beanName);
                }
                //之前标记的开关位。
                if (newSingleton) {
                    //如果是新建的单例,就把单例添加到当前锁的缓存map中,
                    //然后移除在创建过程中在缓存中添加的获取当前bean的BeanFactory对象
                    //然后移除掉为了解决循环依赖而添加在缓存中的单例对象
                    //然后在单例注册map中添加单例对象。
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }

来看匿名对象实现ObjectFactory接口的getObject方法,如下所示,这里只实现了一个createBean方法和校验是否是factory的方法,

            if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

最前面说过,createBean方法对于docreateBean方法来说就是前戏,现在我们来看看createBean都做了些什么

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        if (logger.isDebugEnabled()) {
            logger.debug("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;

        //确认bean在这里被真正的解析了。在动态解析的class中进行那些不能在mbd中储存的bd的克隆
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // 为方法的覆写做准备.
        try {
            //在这里spring做了一些提高效率的操作,在判断当前方法有父类方法时,在父类方法上标记了不重写。
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        try {
            // 在bean初始化之前调用后处理器链。这是spring的扩展功能能实现的关键处,但这不是现在的重点。
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }

        try {
            //哎,你看关键的doCreateBean来了,我们抽出去单独说。
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isDebugEnabled()) {
                logger.debug("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
            // A previously detected exception with proper bean creation context already,
            // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
    }

在这个docreatebean中,5步走

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

        // 第一步:初始化通过Wrapper反射生成bean。
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            //惯例先去缓存map中找
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            //要是空就执行具体的创建实例。这里的具体逻辑就是根据mbd中读取出的不同的策略也就是使用不同的代理类,
            //进行动态代理,反射创建bean,将mbd中及args中的参数挨个反射成wrapper的属性。
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // 这里把后处理器链锁住,然后在这里进行最后一次的属性对象修改。
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }

        // 把需要暴露出来的ObjectBean暴露出来,添加到map缓存中,用于解决循环依赖。
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isDebugEnabled()) {
                logger.debug("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // 初始化bean的实例。
        Object exposedObject = bean;
        try {
            //进行属性填充,通过byname/bytype等方式。
            populateBean(beanName, mbd, instanceWrapper);
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }

        if (earlySingletonExposure) {
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    for (String dependentBean : dependentBeans) {
                        if (!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.");
                    }
                }
            }
        }

        // 注册bean的可销毁方法。
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }

以上就是Spring根据Xml方式获取Bean的配置,并进行加载的全过程。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值