美文网首页探索Spring
Spring Bean生命周期-getBean方法(十)

Spring Bean生命周期-getBean方法(十)

作者: Real_man | 来源:发表于2018-10-15 21:36 被阅读5次

    前面提的基本上都是ApplicationContext的refresh方法,在分析的过程中bean容器的基本启动过程心中有了大体的了解,分析过程中,我们发现bean的实例化及加工相关的处理都在getBean方法中,一起看下getBean方法。

    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }
    

    doGetBean的方法比较长,拆开分析

    分析

    1. 从缓存中,或者获取手动注册的bean,也就是单例的bean已经被创建过了,那么直接获取。
    final String beanName = transformedBeanName(name);
            Object bean;
    
            // Eagerly check singleton cache for manually registered singletons.
            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 + "'");
                    }
                }
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
            }
    

    getObjectForBeanInstance主要做了如下事情:

    • 如果sharedInstance不是FactoryBean的实例,也不是Factory的引用,直接返回sharedInstance
    • 从缓存中获取FactoryBean创建的Bean实例
    • 如果换成中没有,那么使用FactoryBean的getObject方法获取Bean,如果需要postProcess,调用BeanPostProcessor处理bean

    第一步一般都是在bean已经创建过的情况下,也不算是完整的bean创建过程

    1. 在缓存中没有获取的bean的情况下,也就是首次创建bean的时候,判断beanFactory是否有父级beanFactory如果有的话,交给父亲beanFactory完成。
    if (isPrototypeCurrentlyInCreation(beanName)) {
                    throw new BeanCurrentlyInCreationException(beanName);
                }
    
                // Check if bean definition exists in this factory.
                BeanFactory parentBeanFactory = getParentBeanFactory();
                if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                    // Not found -> check parent.
                    String nameToLookup = originalBeanName(name);
                    if (args != null) {
                        // Delegation to parent with explicit args.
                        return (T) parentBeanFactory.getBean(nameToLookup, args);
                    }
                    else {
                        // No args -> delegate to standard getBean method.
                        return parentBeanFactory.getBean(nameToLookup, requiredType);
                    }
                }
    
    
    1. bean的创建过程开始,根据之前解析的bean的依赖,首先创建当前bean实例依赖的bean
            if (!typeCheckOnly) {
                    markBeanAsCreated(beanName);
                }
    
                try {
                    final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                    checkMergedBeanDefinition(mbd, beanName, args);
    
                    // Guarantee initialization of beans that the current bean depends on.
                    // 保证当前创建bean依赖的bean都已经创建了
                    String[] dependsOn = mbd.getDependsOn();
                    if (dependsOn != null) {
                        for (String dependsOnBean : dependsOn) {
                            if (isDependent(beanName, dependsOnBean)) {
                                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                        "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
                            }
                            registerDependentBean(dependsOnBean, beanName);
                            getBean(dependsOnBean);
                        }
                    }
    
    1. 创建bean实例,根据bean的scope执行不同的创建方式。singleton,prototype,其他的scope

    4.1 我们看单例的bean创建方式。其内部调用的是createBean方法。createBean比较重要,放在下次再说

    
        if (mbd.isSingleton()) {
                  // 获取单例,getSingleton方法内部掉的是回调中的getObject方法
                        sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                            @Override
                            public Object getObject() throws BeansException {
                                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);
                    }
    

    4.2 scope为prototype类型的bean创建方式,其在调用createBean前后调用了beforePrototypeCreationafterPrototypeCreation方法,也和singleton类似了。

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

    4.3 不同的socpe创建的bean。只需要实现Scope接口即可。实现scope的get方法,其内部也是使用传入的匿名工厂类getObject

    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, new ObjectFactory<Object>() {
                                @Override
                                public Object getObject() throws BeansException {
                                    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);
                        }
                    }
    
    1. 判断是否需要将bean转换为我们指定类型的class。
    // 调用函数时传递进来的requiredType,bean,并且bean的class类型能转换为requiredType。然后调用TypeConverter进行转换。
    if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
                try {
                    return getTypeConverter().convertIfNecessary(bean, requiredType);
                }
                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());
                }
            }
    
    1. 返回bean。

    最后

    这次我们知道了bean的创建过程其实是在调用getBean的时候创建的。配置的scope也是在这时生效的。

    相关文章

      网友评论

        本文标题:Spring Bean生命周期-getBean方法(十)

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