spring源码分析六(Bean实例化的预处理)

今天这节内容我们一起来研究下,spring的bean的创建,我们一步步看着源码往下分析.下面的方法就会带我们进入bean的创建

完成bean工厂初始化
finishBeanFactoryInitialization(beanFactory);

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // 初始化类型转换器,这一部分的内容,就是说,当前端传过来的数据类型后台不好解析,可以通过这个实现这个接口来实现类类型转换
        //最典型的应用就是data转换
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }

        //如果之前没有任何bean后处理器(例如PropertyPlaceholderConfigurer Bean)之前进行过注册,请注册默认的嵌入式值解析器,
        //主要用于注释属性值的解析
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
        }

        // 初始化 LoadTimeWeaverAwareBean 用于织入第三方模块,在 class 文件载入 JVM 的时候动态织入
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        //将临时类加载器设置为null
        beanFactory.setTempClassLoader(null);

        // 在初始化单例bean的过程中,先暂停bean的注册,解析加载等等
        beanFactory.freezeConfiguration();

        //初始化非懒加载的bean
        beanFactory.preInstantiateSingletons();
    }

其他方法都比较简单,咱们就直接从最后一个方法分析吧,这里干货满满哈
#DefaultListableBeanFactory
@Override
    public void preInstantiateSingletons() throws BeansException {
        if (logger.isTraceEnabled()) {
            logger.trace("Pre-instantiating singletons in " + this);
        }

        //将所有的bean定义名称添加到beanNames集合中
        List beanNames = new ArrayList<>(this.beanDefinitionNames);

        // 遍历所有的费懒加载的bean
        for (String beanName : beanNames) {
            //对bean定义进行合并,比如bean中引入属性parent这一步就是来处理这个属性的
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            //如果bean不是抽象的,不是懒加载的,并且是单例的,执行以下步骤
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                //判断是否是工厂bean
                if (isFactoryBean(beanName)) {
                    //如果是工厂bean,调用的时候再bean的名称前面添加前缀符号&
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                    //再次判断bean是否是factoryBean
                    if (bean instanceof FactoryBean) {
                        final FactoryBean factory = (FactoryBean) bean;
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged((PrivilegedAction)
                                            ((SmartFactoryBean) factory)::isEagerInit,
                                    getAccessControlContext());
                        }
                        else {
                            isEagerInit = (factory instanceof SmartFactoryBean &&
                                    ((SmartFactoryBean) factory).isEagerInit());
                        }
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
                }
                else {
                    getBean(beanName);
                }
            }
        }

        //再次遍历beanNames,对实现了SmartInitializingSingleton接口的类实现处理,这里也就是说,他的功能类似于InitzationBean合格接口
        //在单例bean加载完成后,做一些事情
        for (String beanName : beanNames) {
            Object singletonInstance = getSingleton(beanName);
            if (singletonInstance instanceof SmartInitializingSingleton) {
                final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged((PrivilegedAction) () -> {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }, getAccessControlContext());
                }
                else {
                    smartSingleton.afterSingletonsInstantiated();
                }
            }
        }
    }

//以上的方法都比较简单,我们总结下
1:遍历所有的非懒加载的bean
2:对bean属性中添加了paren的属性执行合并处理
3:判断某个bean是否是工厂bean,如果是,则在bean名称前面添加前缀&再执行处理
4:再次遍历bean,查看bean是否实现了SmartInitializingSingleton,如果实现该接口,在进行回调处理,类似于有点像InitzationBean这个接口

接下来,我们看这个方法中重复出现的一个方法,getBean,没错,就是他,这才是我们要研究的重点,我们一起看看这个方法
代码比较长,我们需要一步步分析啊

AbstractBeanFactory

@Override
    public Object getBean(String name) throws BeansException {
        //主要逻辑在dogetBean中
        return doGetBean(name, null, null, false);
    }

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

            //规范bean名称,就是说,你如果给bean起了别名,我们获取bean的时候,也能找见,这一步就是执行这个操作的
            final String beanName = transformedBeanName(name);
            Object bean;

            // 检查是否已经创建了一个bean实例
            Object sharedInstance = getSingleton(beanName);
            //如果args不为为null,则证明是直接根据beanName获取bean,最终会走到getObjectForBeanInstance
            if (sharedInstance != null && args == null) {
                //1.1通过bean实例获取bean对象
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
            }

            //如果args不为空,则执行以下逻辑,执行创建bean的逻辑
            else {
                //检查当前这个bean是否正在创建,如果正在创建,则直接抛出异常
                if (isPrototypeCurrentlyInCreation(beanName)) {
                    throw new BeanCurrentlyInCreationException(beanName);
                }

                // 检查容器中是否已经存在了当前这个bean
                BeanFactory parentBeanFactory = getParentBeanFactory();
                if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                    //不存在,证明当前容器中不存在这个bean,再去父容器中查看有没有
                    String nameToLookup = originalBeanName(name);
                    if (parentBeanFactory instanceof AbstractBeanFactory) {
                        return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                                nameToLookup, requiredType, args, typeCheckOnly);
                    }
                    else if (args != null) {
                        如果args不为null直接返回父容器的结果
                        return (T) parentBeanFactory.getBean(nameToLookup, args);
                    }
                    else if (requiredType != null) {
                        //如果指定了bean的类类型,在args不为空的情况下,直接返回bean实例
                        return parentBeanFactory.getBean(nameToLookup, requiredType);
                    }
                    else {
                        //从父容器获取一个bean直接返回
                        return (T) parentBeanFactory.getBean(nameToLookup);
                    }
                }

                //这里的typeCheckOnly默认就是false,这里的操作是将当前bean标记为已创建或将要创建
                if (!typeCheckOnly) {
                    markBeanAsCreated(beanName);
                }

                try {
                    //合并bean定义一级检查bean定义
                    final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                    checkMergedBeanDefinition(mbd, beanName, args);

                    // 获取当前bean的依赖,就是spring的属性depneds-on这个属性配置了这个属性全部放入dependsOn数组中
                    String[] dependsOn = mbd.getDependsOn();
                    if (dependsOn != null) {
                        //执行遍历,并检查当前bean的依赖,如果存在循环依赖,直接抛出异常
                        //这里解释下,在spring中,如果A依赖于B,我们使用Autowird注解将B先加载,
                        //但是有个场景,是,B和A没有任何的依赖关系,我们还要让B先加载那,这个depends就起到作用了
                        //也就是说,spring的bean加载是没有指定顺序的,是随意加载,用这个来控制bean的先后加载顺序
                        //如果这里,在两个bean中都配置了相互让对方先加载,就会直接抛出异常
                        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 {
                                //这里是个递归调用,去获取依赖项这个bean
                                getBean(dep);
                            }
                            catch (NoSuchBeanDefinitionException ex) {
                                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                            }
                        }
                    }

                    //这里,我们终于走到了创建bean的逻辑里,这里注意下,对于spring的不同的作用于,
                    //如果是单例的,就走这个逻辑
                    if (mbd.isSingleton()) {
                        sharedInstance = getSingleton(beanName, () -> {
                            try {
                                //创建bean方法
                                return createBean(beanName, mbd, args);
                            }
                            catch (BeansException ex) {
                                //如果抛出异常,直接销毁bean
                                destroySingleton(beanName);
                                throw ex;
                            }
                        });
                        //创建完bean之后,获取当前bean
                        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                    }

                    //如果当前bean的属性是Prototype,则走这个逻辑
                    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;
                }
            }
            =====================================================================================
            // 如果requiredType不为null,并且不是指定的当前bean的实例,则通过转化器处理,如果处理结果任然是null,直接
            //抛出异常
            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.isTraceEnabled()) {
                        logger.trace("Failed to convert bean '" + name + "' to required type '" +
                                ClassUtils.getQualifiedName(requiredType) + "'", ex);
                    }
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
            }
            return (T) bean;
        }

//总结下以上步骤:
1:规范bean的名称,因为bean有可能被起了别名,所以不管是通过原bean还是通过别名,都能访问到
2:检查当前bean实例是否已经创建,如果创建了,而且args参数为null的时候,证明是获取bean,不是创建bean
3:如果args不为null,就执行创建bean的逻辑
4:检查当前容器中是否存在当前的bean,子容器不存在,在区父容器中查找,找到的话,直接返回当前bean
5:将当前bean设置为已创建或将要创建的状态
6:获取bean之间的依赖关系,注意,这里指的是depends-on属性的依赖关系,一定要记清楚,这个是对于两个没有关系的bean,这种依赖,是不允许相互依赖的
7:注册依赖关系,让被依赖项先初始化,存在相互依赖,直接抛出异常
8:对不不同的bean的作用域,执行不同的床架bean操作,singleten,prototype,(request,session,globle-session)
9:对于requiredType不为空的,又不和当前bean实匹配,使用转换器去处理,如果结果还是null,直接抛出异常
以上内容比较简答,我对getBean这个方法做了整体的分析,但是由于篇幅的限制对具体的获取bean和创建bean没有分析,获取bean和创建bean我将分为两章分别介绍!
thanks!

你可能感兴趣的:(spring源码分析六(Bean实例化的预处理))