一文看懂Bean实例化的过程

3 阅读7分钟

前面说到spring启动阶段会扫描bean,生成bean定义注册到容器中。容器刷新后,spring就会进入bean实例化的流程。首先合并bean定义,老版本spring基于xml文件配置bean,会大量存在父bean,此时需要进行处理,将父bean合并到当前bean定义。基于注解的bean定义,spring在扫描到后就会封装成RootBeanDefinition注册到容器中,所以这里注解bean可以不用合并。
实现FactoryBean接口的bean定义注册到容器时,会以FACTORY_BEAN_PREFIX(&)为前缀,实例化bean如果发现当前的bean是FactoryBean则默认不会调用getObject()进行创建bean,只有在注入getObject()生成的bean时才创建bean,除非bean实现SmartFactoryBean接口,则通过方法isEagerInit判断是否需要进行早期实例化,此时不管是否注入都会创建bean。

    public void preInstantiateSingletons() throws BeansException {
        if (logger.isTraceEnabled()) {
            logger.trace("Pre-instantiating singletons in " + this);
        }

        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

        // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {
            //合并bean定义,如果bean存在父bean,则获取父bean定义到自身
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            //实例化单例、非懒加载的bean
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                //通过FactoryBean生成bean时,如果需要注入则启动时实例化,否则等到用到时候实例化
                if (isFactoryBean(beanName)) {
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                    if (bean instanceof FactoryBean) {
                        FactoryBean<?> factory = (FactoryBean<?>) bean;
                        boolean isEagerInit;
                        //如果实现了SmartFactoryBean接口,则判断是否会早期实例化
                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged(
                                    (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                                    getAccessControlContext());
                        }
                        else {
                            isEagerInit = (factory instanceof SmartFactoryBean &&
                                    ((SmartFactoryBean<?>) factory).isEagerInit());
                        }
                        //不管是否存在注入都通过FactoryBean生成bean
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
                }
                else {
                    getBean(beanName);
                }
            }
        }
.......
    }

getBean为spring提供的生成bean实例对象的方法,方法很长,需要一步一步看。spring创建FactoryBean的定义时,会在bean的name前加上FACTORY_BEAN_PREFIX(&),生成的bean实例会去掉FACTORY_BEAN_PREFIX(&),所以现在获取bean实例对象时,需要去掉"&"。然后到缓存中根据name获取实例对象,如果为FactoryBean则判断获取的是工厂bean本身,还是生成的bean。

protected <T> T doGetBean(
            String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
            throws BeansException {
        //bean的名称处理,去掉"&"
        String beanName = transformedBeanName(name);
        Object bean;

        //从缓存中获取bean,如果是FactoryBean则说明需要注入bean,此时会调用getObject方法生成bean
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
......
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            //检查重复创建,存在重复创建说明有循环依赖的问题
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
......      
            //标记当前bean正在被创建
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                //判断是否存在@DependOn导致的循环依赖问题
                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);
                        }
                    }
                }

                //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实例化
                }
                else {
                    String scopeName = mbd.getScope();
                    ......//根据@Scope注解进行处理
                }
            }

        }

......
        return (T) bean;
    }

如果获取的bean为工厂bean,则返回工厂bean本身,这里根据bean的name是否以"&"开头进行判断;没有实现FactoryBean的工厂bean就直接返回;如果不是以"&"开头,并且又实现了FactoryBean接口,则说明需要的是getObject方法生成的bean,则调用getObject方法生成bean,然后缓存下来。

protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

        //获取的bean的name是否为工厂bean,是的话就返回工厂bean本身
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
            }
            if (mbd != null) {
                mbd.isFactoryBean = true;
            }
            return beanInstance;
        }

        //获取的bean为非工厂bean,而是普通bean,直接返回
        if (!(beanInstance instanceof FactoryBean)) {
            return beanInstance;
        }

        Object object = null;
        //根据bean定义获取的FactoryBean,标记即可
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        //先查询缓存
        else {
            object = getCachedObjectForFactoryBean(beanName);
        }
        //调用getObject方法生成bean
        if (object == null) {
            // Return bean instance from factory.
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
            // Caches object obtained from FactoryBean if it is a singleton.
            if (mbd == null && containsBeanDefinition(beanName)) {
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }

接下来是spring解决@DependsOn导致的循环依赖问题,对bean进行实例化的时候,如果不存在循环依赖,则以被依赖的组件为key,将依赖的其他组件添加到set集合,这样就能找出依赖自身的其他组件。判断是否构成循环依赖的设计非常巧妙,首先beanName依赖dep,所以只要判断dep是否依赖beanName就行,那么可以依次获取所有直接或间接依赖beanName的组件,判断是否包含dep,如果dep也在其中,则说明dep也对beanName存在依赖关系,则构成循环依赖。

//遍历当前组件依赖的组件,进行实例化
        for (String dep : dependsOn) {
            //beanName依赖dep,如果dep依赖beanName的话则形成循环依赖了
            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);
            }
        }
    //保存组件的依赖关系,beanName是被依赖的组件,dependentBeanName是依赖其他组件的组件
    public void registerDependentBean(String beanName, String dependentBeanName) {
        String canonicalName = canonicalName(beanName);
        //以被依赖的组件为key,将依赖组件的其他组件添加到set集合
        synchronized (this.dependentBeanMap) {
            Set<String> dependentBeans =
                    this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
            if (!dependentBeans.add(dependentBeanName)) {
                return;
            }
        }
        //将组件作为key,其依赖的所有组件添加到set集合
        synchronized (this.dependenciesForBeanMap) {
            Set<String> dependenciesForBean =
                    this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
            dependenciesForBean.add(canonicalName);
        }
    }
    //判断是否存在依赖关系,beanName为依赖dependentBeanName的组件,只要判断dependentBeanName是否依赖beanName即可、
    //原理是找出所有直接或间接依赖beanName的组件,判断里面是否存在dependentBeanName
    private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
        //alreadySeen表示判断过对beanName不存在依赖关系的组件
        if (alreadySeen != null && alreadySeen.contains(beanName)) {
            return false;
        }
        String canonicalName = canonicalName(beanName);
        //将依赖dependentBeanName的组件beanName作为key,找出所有依赖beanName的组件
        Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
        if (dependentBeans == null) {
            return false;
        }
        //如果存在dependentBeanName,则说明dependentBeanName依赖beanName,构成循环依赖
        if (dependentBeans.contains(dependentBeanName)) {
            return true;
        }
        for (String transitiveDependency : dependentBeans) {
            if (alreadySeen == null) {
                alreadySeen = new HashSet<>();
            }
            alreadySeen.add(beanName);
            //将当前组件的依赖组件作为key,找出依赖当前组件的依赖组件的组件,例如a依赖b,b依赖c,这里就是通过a找出间接依赖自身的c
            //然后判断对自身是否存在依赖关系
            if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
                return true;
            }
        }
        return false;
    }

通过循环依赖的检查后就到对bean进行实例化的逻辑了,首先从缓存中获取,没有获取到则开始实例化,先标记防止重复创建,然后调用传给getSingleton的lambsingletonFactory进行实例化。

    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!)");
                }
                //先标记
                beforeSingletonCreation(beanName);
    ......
                try {
                    //生成bean
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
    ......
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    //取消标记
                    afterSingletonCreation(beanName);
                }
                //缓存已经实例化的bean
                if (newSingleton) {
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }

创建bean的时候,会先尝试通过InstantiationAwareBeanPostProcessor接口和BeanPostProcessor生成bean,这样就不会走spring的实例化流程,算是spring提供的一种扩展机制。

    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {
......
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
......

            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
......
    }

代码简化后逻辑就好看很多,分三步,先反射构造bean的实例对象,再填充bean的属性,再对bean进行实例化。

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {
......
            instanceWrapper = createBeanInstance(beanName, mbd, args);
......
            populateBean(beanName, mbd, instanceWrapper);
            exposedObject = initializeBean(beanName, exposedObject, mbd);
......
        return exposedObject;
    }

首先通过AutowiredAnnotationBeanPostProcessor找出使用@Autowired注解标注的构造器,找不到的话就使用spring解析bean阶段的获取的构造器,还没有的话就是用默认的无参构造函数,找到后就是Java反射创建bean了,填充bean的属性即依赖注入、初始化bean,等之后再讲,这也是一个繁琐的过程。

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
.....
        //找出使用了@Autowired注解的构造器
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        //使用解析阶段指定的构造器
        ctors = mbd.getPreferredConstructors();
        if (ctors != null) {
            return autowireConstructor(beanName, mbd, ctors, null);
        }

        //默认无参构造器
        return instantiateBean(beanName, mbd);
    }

总结下,spring对bean进行实例的时候,首先合并bean定义,然后根据name获取实例,如果是FactoryBean则按情况生成bean,之后处理@DepondOn导致的循环依赖,再找出构造器反射构造bean的实例对象。有不对的地方请大神指出,欢迎大家一起讨论交流,共同进步,更多请关注微信公众号 葡萄开源