美文网首页
spring 知识整理(四):spring bean初始化过程

spring 知识整理(四):spring bean初始化过程

作者: beldon_wu | 来源:发表于2018-07-16 18:32 被阅读0次

    接着上文,来看下DefaultListableBeanFactorygetBean过程。

    BeanFactory有几个getBean的重载方法。但在DefaultListableBeanFactory中,这些重载方法最终会调用AbstractBeanFactory类的一个doGetBean方法。

    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }
    @Override
    public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
        return doGetBean(name, requiredType, null, false);
    }
    @Override
    public Object getBean(String name, Object... args) throws BeansException {
        return doGetBean(name, null, args, false);
    }
    

    追踪doGetBean方法

    下面的缩减的代码

    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
                @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
        final String beanName = transformedBeanName(name);
        Object bean;
        //从缓存中获取单例
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }else {
            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);
                // 创建单例的bean
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }else if (mbd.isPrototype()) {
                    // 创建原型的bean
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }else{
                    //其他类型
                }
            }catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }
        return (T) bean;
    }
    

    从上面代码可以看出spring在getBean的时候主要做了两个操作:

    • 从缓存中获取Bean对象
    • 若缓存中不存在Bean对象,则执行创建bean的操作

    为了弄清流程,我们还是先弄懂spring单例的创建过程。

    spring单例的创建过程

    从上面的代码可以抽取一下创建单例的代码。

    sharedInstance = getSingleton(beanName, () -> {
        try {
            return createBean(beanName, mbd, args);
        }
        catch (BeansException ex) {
            destroySingleton(beanName);
            throw ex;
        }
    });
    

    从上面可以看出,创建单例的时候主要是调用了getSingleton的方法,该方法第一个参数是beanName,第二个参数是一个ObjectFactory,从名字上就可以看出来,ObjectFactory主要是用来创建对象的。而这个ObjectFactory主要也是调用AbstractAutowireCapableBeanFactorycreateBean方法。createBeanbeanNameRootBeanDefinitionarg传输进去。好,先看看getSingleton的代码

    getSingleton方法

    getSingleton方法是AbstractBeanFactory的父类DefaultSingletonBeanRegistry中的方法。DefaultSingletonBeanRegistry从名字可以看出主要是为了单例而创建的。

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        synchronized (this.singletonObjects) { //加锁
            //从缓存中获取对象
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                //缓存中获取不到对象,则开始创建对象
                //判断容器是否在销毁,若是在销毁,则直接跑一次。
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,"");
                }
                //创建前校验,主要是检查排除的bean和把beanName放到singletonsCurrentlyInCreation的map中去
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    //通过ObjectFactory去创建Object
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                catch (IllegalStateException ex) {
                    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;
                    }
                    //创建后主要检查排除的bean和把beanName从singletonsCurrentlyInCreation的map中移除
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    //如果是创建则把生成的对象添加到缓存中去
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }
    

    从上面代码中可以看出,getSingleton方法主要任务是确保并发,确保只创建一个单例,而且具体创建对象还是交给ObjectFactory创建,等对象创建完成后,缓存对象。

    protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
            this.singletonObjects.put(beanName, singletonObject);
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
    

    上面是缓存对象的方法,主要也是把对象放到singletonObjectsregisteredSingleton两个Map中去。

    再回头看看createBean方法。

    createBean

    追踪下AbstractAutowireCapableBeanFactorycreateBean方法

    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
        RootBeanDefinition mbdToUse = mbd;
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }
        try {
            //准备prepare方法
            //主要是处理的lookup-method、replace-method方法,若找到相应的的方法,则进行标记
            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.
            //嗯,上面描述很明确了,给机会BeanPostProcessors去返回一个代理类,如果不返回代理类则继续
            //BeanPostProcessors是只实现InstantiationAwareBeanPostProcessor接口的类,实现接口的类可以自定义生成自己的bean
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse); //标记1️⃣
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                                       "BeanPostProcessor before instantiation of bean failed", ex);
        }
        try {
            //嗯,这里就开始真正创建类了
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isDebugEnabled()) {
                logger.debug("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(),
                               beanName, "Unexpected exception during bean creation", ex);
        }
    }
    

    跟踪下标记1️⃣中的方法,看看里面到底是怎么回事

    resolveBeforeInstantiation
    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;
    }
    

    再追踪下applyBeanPostProcessorsBeforeInstantiationapplyBeanPostProcessorsAfterInitialization

    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;
    }
    
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }
    

    原来是给机会BeanPostProcessor和它的子接口InstantiationAwareBeanPostProcessor的机会,也就是说我们实现这两个接口的bean就可以处理自己的对象生成规则了,666的。

    好了,在深究下doCreateBean方法,听说java中do开都的方法都是真正做事的方法

    doCreateBean
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
                throws BeanCreationException {
        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            //创建实例的BeanWrapper
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        //从beanWrapper里面获取包装类对象
        final Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }
        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    //调用MergedBeanDefinitionPostProcessor
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                        "Post-processing of merged bean definition failed", ex);
                }
                mbd.postProcessed = true;
            }
        }
    
        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                                          isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }
        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            //属性注入
            populateBean(beanName, mbd, instanceWrapper);
            //进行 init-method初始化,主要是通知各个BeanPostProcessor
            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,  "");
                    }
                }
            }
        }
        // Register bean as disposable.
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }
        return exposedObject;
    }
    

    doCreateBean方法主要是做了以下事情:

    • createBeanInstance 生成对象,并返回包装类
    • popoulateBean 进行属性注入
    • instantiateBean 进行init-method初始化和后置等处理,主要是通知各个BeanPostProcessor

    总结

    贴的代码有点多,创建对象的一些逻辑还没深究,继续下去就怕很难闭合了。倒不如先来个总结。

    image

    相关文章

      网友评论

          本文标题:spring 知识整理(四):spring bean初始化过程

          本文链接:https://www.haomeiwen.com/subject/ymvzuftx.html