Spring-IOC-SingletonBean的创建过程

如果缓存中没有单例Bean的缓存,则需要从头开始创建单例Bean,这主要是重载getSingleton的重载方法来实现单例Bean的加载。

getSingleton方法

3. 获取单例
    /**
     * Return the (raw) singleton object registered under the given name,
     * creating and registering a new one if none registered yet.
     * @param beanName the name of the bean
     * @param singletonFactory the ObjectFactory to lazily create the singleton
     * with, if necessary
     * @return the registered singleton object
     */
    public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
        Assert.notNull(beanName, "'beanName' must not be null");
        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 + "'");
                }
                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;
                    }
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    addSingleton(beanName, singletonObject);
                }
            }
            return (singletonObject != NULL_OBJECT ? singletonObject : null);
        }
    }

前后处理方法:

3.1 
    /**
     * Callback before singleton creation.
     * 

The default implementation register the singleton as currently in creation. * @param beanName the name of the singleton about to be created * @see #isSingletonCurrentlyInCreation */ protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } } 3.2 /** * Callback after singleton creation. *

The default implementation marks the singleton as not in creation anymore. * @param beanName the name of the singleton that has been created * @see #isSingletonCurrentlyInCreation */ protected void afterSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) { throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation"); } } 3.3 /** * Add the given singleton object to the singleton cache of this factory. *

To be called for eager registration of singletons. * @param beanName the name of the bean * @param singletonObject the singleton object */ protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT)); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } 3.4 从3返回 sharedInstances = getSingleton(String beanName, ObjectFactory singletonFactory)

这个方法只是做一些准备以及处理操作,而真正的获取单例bean的方法其实并不是在此方法中实现的,其实现逻辑是在ObjectFactory类型的实例singletonFactory中实现的。

准备及处理操作如下:

  1. 首先获取SingletonObjects的对象锁,保证单例的全局唯一性。

  2. 检查缓存是否已经加载过。

  3. 若没有加载,则记录beanName的正在加载状态

  4. 加载单例前记录加载状态

    beforeSingletonCreation()方法用于记录加载的状态:
    调用this.singletonsCurrentlyInCreation.add(beanName)将当前正要创建的bean记录在缓存中,这样便可以对循环依赖进行检测啦

  5. 通过调用参数传入的ObjectFactory的getObject方法实例化bean

    singletonObject = singletonFactory.getObject();

  6. 加载单例后的处理方法调用

    当bean加载结束后需要移除缓存中对该bean的正在加载状态的记录: afterSingletonCreation()方法调用

  7. 将结果记录至缓存并删除加载bean过程中所有记录的各种辅助状态

    调用addSingleton()方法

  8. 返回处理结果

    上述是加载bean的逻辑框架,现在为止还没有对bean加载功能的探索,其实bean的加载逻辑是在传入的ObjectFactory类型的参数singletonFactory中定义的,而ObjectFactory的核心代码只是调用了createBean的方法,接下来就去探究一下这个方法的奥妙。

createBean方法详解

准备创建bean(createBean方法详解)
beans.factory.support.AbstractAutowireCapableBeanFactory
    //---------------------------------------------------------------------
    // Implementation of relevant AbstractBeanFactory template methods
    //---------------------------------------------------------------------

    /**
     * Central method of this class: creates a bean instance,
     * populates the bean instance, applies post-processors, etc.
     * @see #doCreateBean
     */
    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;

        // Make sure bean class is actually resolved at this point, and
        // clone the bean definition in case of a dynamically resolved Class
        // which cannot be stored in the shared merged bean definition.
        Class resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // Prepare method overrides.
        try {
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            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);
        }

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

createBean方法主要步骤:

  1. 根据设置的class属性或者根据className来解析Class。

  2. 对override属性进行标记以及验证(是针对Spring配置中lookup-method、replace-method bean的子标签进行处理,因为这两个子标签的加载过程就是将配置统一存放在BeanDefinition中的methodOverride属性里)。

  3. 应用实例前的后处理器,给后处理器一个返回代理而不是目标bean实例的机会,如果返回的代理类不为空则直接返回,而不会进行下面的创建bean的过程。

  4. 创建bean(doCreateBean方法)。这又是一个比较重要而且复杂的过程,需要仔细分析。

下面重点讲解步骤2、3、4。

步骤2- 处理override属性

用于处理配置中的lookup-method以及replace-method属性。

主要完成的工作:

  1. 标记

如果一个类中存在若干个重载方法,方法调用以及增强的时候还需要根据参数类型进行匹配,来最终确定当前调用的是哪个方法,Spring在这里将匹配的工作在这里完成匹配的,这样在后续调用的时候变可以直接是我用找到的方法,而不需要进行方法的参数匹配验证了

  1. 验证

在标记的过程中可以对方法存在性进行验证,一箭双雕。

4.1 处理override属性
beans.factory.support.AbstractBeanFactory(XmlBeanFactory 继承自这个类,拥有这个方法)
    /**
     * Validate and prepare the method overrides defined for this bean.
     * Checks for existence of a method with the specified name.
     * @throws BeanDefinitionValidationException in case of validation failure
     */
    public void prepareMethodOverrides() throws BeanDefinitionValidationException {
        // Check that lookup methods exists.
        MethodOverrides methodOverrides = getMethodOverrides();
        if (!methodOverrides.isEmpty()) {
            Set overrides = methodOverrides.getOverrides();
            synchronized (overrides) {
                for (MethodOverride mo : overrides) {
                    prepareMethodOverride(mo);
                }
            }
        }
    }
    /**
     * Validate and prepare the given method override.
     * Checks for existence of a method with the specified name,
     * marking it as not overloaded if none found.
     * @param mo the MethodOverride object to validate
     * @throws BeanDefinitionValidationException in case of validation failure
     */
    protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
        int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
        if (count == 0) {
            throw new BeanDefinitionValidationException(
                    "Invalid method override: no method with name '" + mo.getMethodName() +
                    "' on class [" + getBeanClassName() + "]");
        }
        else if (count == 1) {
            // Mark override as not overloaded, to avoid the overhead of arg type checking.
            mo.setOverloaded(false);
        }
    }

步骤3- 实例化前的的后处理

doCreateBean()方法之前调用了resolveBeforeInstantiation方法对BeanDefinition中的属性进行前置处理。

  1. 调用实例化前处理器进行处理。

  2. 短路判断:如果前置处理返回的结果不为空,则直接略过后续Bean的创建而直接返回结果,这一特性至关重要,AOP功能就是基于这里的判断的,如果不为空则调用初始化后处理器。

实例化的前置处理
beans.factory.support.AbstractAutowireCapableBeanFactory
    /**
     * Apply before-instantiation post-processors, resolving whether there is a
     * before-instantiation shortcut for the specified bean.
     * @param beanName the name of the bean
     * @param mbd the bean definition for the bean
     * @return the shortcut-determined bean instance, or {@code null} if none
     */
    protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            // Make sure bean class is actually resolved at this point.
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                Class targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }

4.2.1 初始化前的后处理器
    /**
     * Apply InstantiationAwareBeanPostProcessors to the specified bean definition
     * (by class and name), invoking their {@code postProcessBeforeInstantiation} methods.
     * 

Any returned object will be used as the bean instead of actually instantiating * the target bean. A {@code null} return value from the post-processor will * result in the target bean being instantiated. * @param beanClass the class of the bean to be instantiated * @param beanName the name of the bean * @return the bean object to use instead of a default instance of the target bean, or {@code null} * @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation */ protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); if (result != null) { return result; } } } return null; } 4.2.2 实例化后的后处理器 @Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessAfterInitialization(result, beanName); if (result == null) { return result; } } return result; }

实例化前的后处理器的应用

将AbstractBeanDefinition转换为BeanWrapper前的处理,给子类一个修改BeanDefinition的机会,也就是说当程序经过这个方法之后,bean可能已经不是我们认为的bean了,而是或许成为一个经过处理的代理bean,可能是通过cglib生成的,也可能是通过其他技术生成的,会在AOP中进行讲解,需要清楚的是在bean的实例化前会调用后处理器的方法进行处理。

初始化后的后处理器

Spring保证bean初始化后尽可能将注册的后处理器postProcessAfterInitialization方法应用到该bean中。

步骤4- doCreateBean方法详解

见Spring-IOC-循环依赖检测与Bean的创建

你可能感兴趣的:(Spring-IOC-SingletonBean的创建过程)