• AbstractBeanFactory#getBean(beanName)


    由于 getBean 内容比较多, 所以单独出来, 接着上一篇的顺序来看.

    //org.springframework.beans.factory.support.AbstractBeanFactory#getBean
    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }

    doGetBean里面, 有一堆乱七八糟的判断,

    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    
        /**
         * 通过 name 获取 beanName。这里不使用 name 直接作为 beanName 有两个原因
         * 1、name 可能会以 & 字符开头,表明调用者想获取 FactoryBean 本身,而非 FactoryBean
         *   实现类所创建的 bean。在 BeanFactory 中,FactoryBean 的实现类和其他的 bean 存储
         *   方式是一致的,即 <beanName, bean>,beanName 中是没有 & 这个字符的。所以我们需要
         *   将 name 的首字符 & 移除,这样才能从缓存里取到 FactoryBean 实例。
         * 2、还是别名的问题,转换需要
         * &beanName
         */
        final String beanName = transformedBeanName(name);
        Object bean;
    
        // Eagerly check singleton cache for manually registered singletons.
        /**
         * 这个方法在初始化的时候会调用,在getBean的时候也会调用
         * 为什么需要这么做呢?
         * 也就是说spring在初始化的时候先获取这个对象
         * 判断这个对象是否被实例化好了(普通情况下绝对为空====初始化完之后, 此处返回就不是空了)
         * 从spring的bean容器中获取一个bean,由于spring中bean容器是一个map(singletonObjects)
         * 所以你可以理解getSingleton(beanName)等于beanMap.get(beanName)
         * 由于方法会在spring环境初始化的时候(就是对象被创建的时候调用一次)调用一次
         * 还会在getBean的时候调用一次
         *
         * 需要说明的是在初始化时候调用一般都是返回null
         */
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            if (logger.isTraceEnabled()) {
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            /**
             * 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。
             * 但如果 sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的 bean 实例。
             * 如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回即可。
             * 毕竟 FactoryBean 的实现类本身也是一种 bean,只不过具有一点特殊的功能而已。
             */
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
        else {
            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            /**
             * 原型模式
             * 如果是原型不应该在初始化的时候创建
             */
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
    
            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
               ......
            }
    
            if (!typeCheckOnly) {
                //添加到 alreadyCreated set集合当中,表示他已经创建过一场
                markBeanAsCreated(beanName);
            }
    
            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                //bd检测, 如果是 abstract, 则抛异常
                checkMergedBeanDefinition(mbd, beanName, args);
    
                // Guarantee initialization of beans that the current bean depends on.
                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);
                        }
                    }
                }
    
                // Create bean instance.
                // 单例创建
                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);
                }
    
                else if (mbd.isPrototype()) {
                    ......
                }
    
                else {
                    ......
                }
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }
    
        // Check if required type matches the type of the actual bean instance.
        if (requiredType != null && !requiredType.isInstance(bean)) {
            ......
        }
        return (T) bean;
    }

    方法比较长, 我删掉一部分. 不影响观看.

    主要看两个方法 :

    1.getSingleton(String beanName, ObjectFactory<?> singetonFactory)

    2.createBean

    getSingleton

    org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name 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 + "'");
                }
                /**
                 * 将beanName添加到singletonsCurrentlyInCreation这样一个set集合中
                 * 表示beanName对应的bean正在创建中
                 */
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    //这里会调用传入的 lambda 表达式创建的匿名 singletonFactory 对象, 调用他的 getObject() 方法
                    //其方法内部, 也就是调用 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean 方法
                    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;
        }
    }

     这里的getSingleton , 明显是一个创建 bean 的地方. 

    1. 在创建之前, 通过 beforeSingletonCreation() 方法, 执行了  this.singletonsCurrentlyInCreation.add(beanName) 这句代码,

    这里其实是在做一个标志, 表示 这个 beanName 对应的 bean 正在创建当中. 将 singletonsCurrentlyInCreation 翻译过来, 就能看懂. 

    这里做到了变量名的命名就是最好的注释.

    2. 调用 factory.getObject 方法, 进行 bean 的创建, 调用的其实就是 createBean() 方法.

    3. 创建完成之后, 通过 afterSingletonCreation() 方法, 将标志位改回去, 其内部执行了 this.singletonsCurrentlyInCreation.remove(beanName) 这句代码.

    4. 在最后, 通过 addSingleton() 方法, 将创建的 bean 放到 spring 容器中 : this.singletonObjects.put(beanName, singletonObject)

     这里的这个顺序很重要, 尤其是那个 正在创建的标志, 很重要的 : singletonsCurrentlyInCreation 

    这个正在创建的标志, 在解决 循环依赖的时候, 起了很重要的作用

    createBean

    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean

    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {
    
        if (logger.isTraceEnabled()) {
            logger.trace("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.
        //处理xml中的 lookup-method 和 replace-method 配置,Spring将这两个配置统称为override method
        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.
            // 在 bean实例化之前 应用后置处理,如果后置处理返回的bean不为空,则直接返回
            // 返回的是一个寡妇对象, 属性什么的, spring不会去维护
            // spring不推荐开发人员使用这个接口 InstantiationAwareBeanPostProcessor
            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 {
            // 创建bean
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isTraceEnabled()) {
                logger.trace("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);
        }
    }

    在 spring 里面, 有一个习惯, 喜欢把 真正干活的那个方法, 以 do 开头.

    所以, 这个 doCreateBean() 方法, 应该就是干活方法.

    不过在此之前, 要看一个重要扩展方法: resolveBeforeInstantiation

  • 相关阅读:
    解决HTML乱码
    <img> 标签的 src 属性
    tomcat 启动报错 解决办法 A child container failed during&nbsp
    SpringMVC拦截器(资源和权限管理)
    Java实现文件上传-按钮弹出上传页面
    Socket规划中的局域网内测试
    iOS pragma mark要使用
    dwz 照片回头处理
    图像显示和逐渐消失
    讲座:采用Store检查邮件(1)
  • 原文地址:https://www.cnblogs.com/elvinle/p/13364743.html
Copyright © 2020-2023  润新知