欢迎您的访问
专注架构,Java,数据结构算法,Python技术分享

深入理解Spring IOC(四)、 实例化开启

接下来我们进入AbstractApplicationContext中的finishBeanFactoryInitialization这个方法,我们先一起看看它的代码:

                                                                代码块1
        protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // 先实例化ConversionService(如果有)
        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));
        }

        // 实例化LoadTimeWeaverAware的实现类
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        // Stop using the temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(null);

        // 在这里要将beanDefiniton冻结住,因为要进行实例化了,不希望beanDefiniton有任何的变化
        beanFactory.freezeConfiguration();

        // 要实例化几乎除过实现了BeanFactoryPostProcessor、BeanPostProcessor的类之外的所有类
        // 因为这两个的实现类之前已经实例化过了
        beanFactory.preInstantiateSingletons();
    }

前面的代码不属于重要的部分,我们直接看最后一处的方法preInstantiateSingletons,该方法的实现位于DefaultListableBeanFactory中:

                                                                代码块2
        @Override
    public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Pre-instantiating singletons in " + this);
        }

        List<String> beanNames;
        synchronized (this.beanDefinitionMap) {
            // this.beanDefinitionNames,创建beanDefinitionNames的副本beanNames
            // 用于后续的遍历,以允许init等方法注册新的bean定义
            // this.beanDefinitionNames 中存储的是在注册BeanDefinition的时候存进来的bean名称
            beanNames = new ArrayList<String>(this.beanDefinitionNames);
        }
        // 遍历,用bean名称初始化
        for (String beanName : beanNames) {
            // 获取beanName对应的RootBeanDefinition
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);

            // 如果不是抽象并且是单例,并且不是懒加载,才会去进行初始化
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                // 1. 如果不是FactoryBean就直接初始化,是的话先拿到FactoryBean本身,再根据isEagerInit决定
                // 是否调用getObject进行初始化
                if (isFactoryBean(beanName)) {
                    final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                    boolean isEagerInit;
                    // 2.这个if else主要是用于判断是否需要先加载(饥饿加载)
                    // isEagerInit这个变量值其实就是SmartFactoryBean中isEagerInit()方法,只不过一个是直接获取,
                    // 另外一个是通过“特权”去执行
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                            @Override
                            public Boolean run() {
                                return ((SmartFactoryBean<?>) factory).isEagerInit();
                            }
                        }, getAccessControlContext());
                    } else {
                        isEagerInit = (factory instanceof SmartFactoryBean &&
                                ((SmartFactoryBean<?>) factory).isEagerInit());
                    }

                    // 如果isEagerInit则实例化bean
                    if (isEagerInit) {
                        getBean(beanName);
                    }
                } else {
                    getBean(beanName);
                }
            }
        }
    }

我们来看代码块2的1处调用的isFactoryBean方法

代码块2.1

                                                                代码块3
        @Override
    public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
        // 1. 处理名称
        String beanName = transformedBeanName(name);

        // 2. 从缓存中拿实例并判断
        Object beanInstance = getSingleton(beanName, false);
        if (beanInstance != null) {
            return (beanInstance instanceof FactoryBean);
        // 如果this.singletonObjects包含这个beanName的key,则直接返回false
        }else if (containsSingleton(beanName)) {
            return false;
        }

        // 从beanDefinition中做检查
        // 本BeanFactory对象中没有这个beanName的BeanDefinition && 父BeanFactory是个ConfigurableBeanFactory
        if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
            return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
        }

        // 根据class判断是不是个FactoryBean
        return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
    }

首先看看代码块3中1处处理名称的逻辑:

代码块3.1

                                                                代码块4
    protected String transformedBeanName(String name) {
        // 调用canonicalName方法去处理BeanFactoryUtils.transformedBeanName的结果
        return canonicalName(BeanFactoryUtils.transformedBeanName(name));
    }

上面代码块调用的方法参数是BeanFactoryUtils中的transformedBeanName返回的,我们先来看这个方法:

                                                                代码块5
    public static String transformedBeanName(String name) {
        Assert.notNull(name, "'name' must not be null");
        String beanName = name;
        // beanName 是否以 “&” 开头,如果以它开头,将这个用String中的substring方法截掉
        while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
            beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        }
        return beanName;
    }

很多人会疑惑,为什么以“&”开头,就截取掉呢?我们来看看BeanFactory中定义的“&”的地方:

                                                                代码块6
public interface BeanFactory {

    /**
     * Used to dereference a {@link FactoryBean} instance and distinguish it from
     * beans <i>created</i> by the FactoryBean. For example, if the bean named
     * {@code myJndiObject} is a FactoryBean, getting {@code &myJndiObject}
     * will return the factory, not the instance returned by the factory.
     */
    String FACTORY_BEAN_PREFIX = "&";
.....

我们可以清楚的从这个变量的注释上面看到:如果某个bean是个FactoryBean类型的东西,但是它注册进IOC容器的名称是用“&”开头,那么代表它想获取的是FactoryBean本身,而不是它的getObject所返回的对象。因此,去拿真正的bean的名称的时候是需要去掉这个前缀的。然后我们继续看代码块4调用的这个canonicalName方法

代码块4.1

                                                                代码块7
        public String canonicalName(String name) {
        String canonicalName = name;
        // Handle aliasing...
        String resolvedName;
        do {
            // 去根据别名拿真正的名称
            // aliasMap的key是别名,value是名称
            resolvedName = this.aliasMap.get(canonicalName);
            if (resolvedName != null) {
                canonicalName = resolvedName;
            }
        }
        while (resolvedName != null);
        return canonicalName;
    }

我们再回到代码块3,来看里面2处的方法,注意此时第二个参数是false:

代码块3.2

                                                                代码块8
        protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 先尝试从成品的缓存中拿成品
        Object singletonObject = this.singletonObjects.get(beanName);
        // 如果没成品并且正在创建中
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                // 从提前曝光的对象中尝试获取
                singletonObject = this.earlySingletonObjects.get(beanName);
                // ***** 如果半成品也是null并且允许创建早期的单例引用,
                if (singletonObject == null && allowEarlyReference) {
                    // 去拿对象的ObjectFactory
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        // 通过ObjectFactory创建半成品,然后放到半成品对象的缓存中
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }

注意注释中*开头的,因为此时传过来的参数是false,所以在这之后的代码此时都是没有被执行的。这段代码涉及到三层缓存的概念,所谓的三层缓存,其实就是singletonObjects,earlySingletonObjects,singletonFactories这三个Map,这三层缓存对解决循环依赖有着重要的意义,如果你现在不明白,就当混个脸熟,完了回过头来看,相信会容易理解很多,现在可以理解为这个方法就是从缓存里取已经创建的bean实例的。

代码块2.2

我们继续看代码块2的第2处isEagerInit属性的获取这里,因为对于spring来说,它去拿这个isEagerInit属性,很可能是去调用第三方jar包的东西,而这个第三方jar包却需要操作一些需要权限才可以操作的东西,因此这里如果检测到SecurityManager,说明程序是有权限校验的,这时候就需要通过AccessController.doPrivileged来执行。我们接下来看这里调用的getBean方法:

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

可以看到这个方法是直接调用的doGetBean,我们来看看这个方法:

                                                                代码块10
        @SuppressWarnings("unchecked")
    protected <T> T doGetBean(
            final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {

        // 1. 解析bean的名称
        final String beanName = transformedBeanName(name);
        Object bean;

        // 2.先尝试从缓存中取一波
        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 + "'");
                }
            }
            // 3. 这块这个主要是针对FactoryBean的处理,如果只是个普通bean,则直接返回其本身
            // 如果是个FactoryBean,则要根据name判断
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        } else {
            // 4. 这个主要针对的是prototype(多例)的bean的循环依赖的检查(spring解决不了多例的循环依赖)
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            BeanFactory parentBeanFactory = getParentBeanFactory();
            // 如果父BeanFactory存在,并且本BeanFactory中不存在这个beanName的BeanDefinition
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // 5. 将别名解析成真正的bean的名字
                String nameToLookup = originalBeanName(name);
                // 使用父BeanFactory创建实例
                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);
                }
            }

            // 6. 如果不是仅仅检查类型,则把beanName放到alreadyCreated缓存中
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            // 注意哈:其实到这里,真正创建bean的流程才开始
            try {
                // 7. 拿到这个beanName对应的BeanDefinition对应的RootBeanDefinition
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

                // 将mbd打印成json (这是作者自己增加的代码)
                System.out.println(JSON.toJSON(mbd).toString());

                // 8. 检查这个mbd是否合法
                checkMergedBeanDefinition(mbd, beanName, args);

                // 先实例化这个bean所依赖的bean,mbd.getDependsOn()是获取mbd所
                // 依赖的bean实例的名称(xml中对应bean标签depend-on属性)
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dependsOnBean : dependsOn) {
                        // 这块这个是检查循环依赖的
                        // 例:如果有这么两个类A和B,A中有个成员属性B,B中有个成员属性A,当先实例化A的时候,发现B还没有实例化
                        // 然后去调用上面的getBean方法(相当于递归),然后走到这里发现B又依赖A,然后就报异常了
                        // 这个会在两个bean标签的depend-on属性相互指向对方时发生
                        if (isDependent(beanName, dependsOnBean)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
                        }
                        // 9. 将依赖关系注册
                        registerDependentBean(dependsOnBean, beanName);
                        // 然后实例化依赖的那个bean
                        getBean(dependsOnBean);
                    }
                }

                // 这里开始创建mbd对应的bean

                // 创建单例
                if (mbd.isSingleton()) {
                    // 10. 获取bean实例
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {
                                //  调用创建bean的方法
                                return createBean(beanName, mbd, args);
                            }catch (BeansException ex) {
                                destroySingleton(beanName);
                                throw ex;
                            }
                        }
                    });
                    // 返回bean本身,(这个方法我们之前讲过,是针对FactoryBean处理的那个方法)
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                // 创建prototype的bean
                }else if (mbd.isPrototype()) {
                    // 如果是个prototype的实例,那就创建个新的
                    Object prototypeInstance = null;
                    try {
                        // 11. 创建prototype前的检查
                        beforePrototypeCreation(beanName);
                        // 调用创建bean的方法
                        prototypeInstance = createBean(beanName, mbd, args);
                    }finally {
                        // 12.创建prototype后的检查
                        afterPrototypeCreation(beanName);
                    }
                    // 返回bean本身,(和上面if一个方法)
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                // 创建其他scope的bean
                }else {
                    String scopeName = mbd.getScope();
                    // 拿到对应scope的缓存
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
                    }
                    try {
                        // 创建bean实例,注意这里重写了ObjectFactory的getObject方法
                        Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                            @Override
                            public Object getObject() throws BeansException {
                                // 创建prototype前的检查
                                beforePrototypeCreation(beanName);
                                try {
                                    // 调用创建bean的方法
                                    return createBean(beanName, mbd, args);
                                }finally {
                                    // 创建prototype后的检查
                                    afterPrototypeCreation(beanName);
                                }
                            }
                        });
                        // 返回bean本身,(和上面if一个方法)
                        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;
            }
        }

        // 检查类型,如果不是结果所需要的类型,则尝试类型转换
        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());
            }
        }
        return (T) bean;
    }

这个方法代码比较长,我们对着我的注释,一个一个来看,1处在上面已经讲过,这里和上面的逻辑是完全一样的,我们来看代码块10中2处的代码所调用的方法:

代码块10.2

                                                            代码块11
        @Override
    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }

这里调用的方法还是代码块8的那个方法,只不过注意此时参数为true了,true和上面的false有什么区别呢?我们可以翻到代码块8看看,当这个参数为true的时候,是允许使用ObjectFactory来创建早期的引用的,不过你可能还不明白什么是早期引用,没关系,先记住这个问题,继续往下看,自然会明白。

我们继续回到代码块10中,去看第3处代码,你应该注意到,能走到这处,说明上面从缓存中取出来的sharedInstance应该不是null,并且本方法参数中args要为null,我们在代码块9中可以看到args确实是null,所以可以肯定,如果sharedInstance不是null,那的确是可以进到3这里来的:我们来看看3处调用的方法。

代码块10.3

                                                            代码块12
        protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

        // 1.如果名称是个factorybean前缀(&)开头的但是却不是FactoryBean,则抛出异常
        //  (当bean名称前缀是“&”的时候,代表这玩意是个FactoryBean的实例)
        if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
        }

        // 2.if的前半个条件意思是如果不是FactoryBean,则直接返回beanInstance
        //   后半个条件是当是个FactoryBean的时候,并且用&开头,则返回beanInstance
        // (以“&”为前缀代表想获取的是FactoryBean本身,而不是它getObject返回的)
        if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
            return beanInstance;
        }

        // 3.当代码走到这里的时候,beanInstance一定是一个FactoryBean
        //  并且想要返回的是FactoryBean中getObject所返回的,object即为返回的结果
        Object object = null;
        if (mbd == null) {
            //4. 尝试从factoryBeanObjectCache(factoryBean创建的对象的缓存)里拿
            object = getCachedObjectForFactoryBean(beanName);
        }
        // 如果从factoryBean创建的对象的缓存没拿到,就走这个if
        if (object == null) {
            //5. 因为一定是FactoryBean,所以可以直接强转
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
            //6. 如果mbd为空,并且beanDefinitionMap中包含着这个bean,则去根据这个获取RootBeanDefinition
            if (mbd == null && containsBeanDefinition(beanName)) {
                // 7. 获取beanName对应的RootBeanDefinition
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            //8. 判断Beaneifinition是不是合成的(多次debug这里都是false)
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }

第1处的注释写的很清楚,我们来看看它调用的方法:

                                                            代码块13
        public static boolean isFactoryDereference(String name) {
        // BeanFactory.FACTORY_BEAN_PREFIX 值是“&”
        return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
    }

是不是很简单?其实源码中很多地方也没那么难的,第2处也很简单了,我们来看看第4处调用的方法的代码:

                                                            代码块14
        // 下面方法调用的cache
    private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<String, Object>(16);

    protected Object getCachedObjectForFactoryBean(String beanName) {
        // factoryBeanObjectCache就是factoryBean创建的对象的缓存
        Object object = this.factoryBeanObjectCache.get(beanName);
        return (object != NULL_OBJECT ? object : null);
    }

这个也是个很简单的方法,我们继续看代码块12中的第6处的这个if条件里调用的方法:

                                                            代码块15
        @Override
    public boolean containsBeanDefinition(String beanName) {
        Assert.notNull(beanName, "Bean name must not be null");
        return this.beanDefinitionMap.containsKey(beanName);
    }

这个beanDefinitionMap就是我们之前讲注册beanDefinition时候的那个map,我们再继续看代码块12中的第8处代码,注意我把第7处的跳过了哈,因为现在不是讲这个第7处方法调用的代码的最好时候,你现在先去根据注释理解,等该讲的时候,我会让你一下子明白的。

                                                            代码块16
        protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        //  FactoryBean实例是单例 && FactoryBean实例已经存在单例缓存this.singletonObjects中
        if (factory.isSingleton() && containsSingleton(beanName)) {
            // getSingletonMutex()返回的是单例缓存this.singletonObjects
            synchronized (getSingletonMutex()) {
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {
                    // 1. 使用factoryBean创建bean
                    object = doGetObjectFromFactoryBean(factory, beanName);
                    // 如果缓存中已经存在,则用缓存中的替换上面生成的
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    if (alreadyThere != null) {
                        object = alreadyThere;
                    }else {
                        // 2. 既然object已经生成了,则执行所有BeanPostProcessor的
                        //  postProcessAfterInitialization方法
                        if (object != null && shouldPostProcess) {
                            try {
                                object = postProcessObjectFromFactoryBean(object, beanName);
                            }catch (Throwable ex) {
                                throw new BeanCreationException(beanName,
                                        "Post-processing of FactoryBean's singleton object failed", ex);
                            }
                        }
                        // 放入factoryBeanObjectCache缓存
                        this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
                    }
                }
                return (object != NULL_OBJECT ? object : null);
            }
        }else {
            // 使用factoryBean创建bean,然后再执行所有的BeanPostProcessor(和上面一样)
            // 不同点是prototype这种情况的话,不会放到缓存中
            Object object = doGetObjectFromFactoryBean(factory, beanName);
            if (object != null && shouldPostProcess) {
                try {
                    object = postProcessObjectFromFactoryBean(object, beanName);
                }catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                }
            }
            return object;
        }
    }

直接来看代码块16里第1处调用的方法:

                                                            代码块17
        private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
            throws BeanCreationException {

        Object object;
        try {
            // 就是简单调用了FactoryBean的getObject而已,只不过if
            // 代码块的是特权调用,else里是直接调用
            if (System.getSecurityManager() != null) {
                AccessControlContext acc = getAccessControlContext();
                try {
                    object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        @Override
                        public Object run() throws Exception {
                                return factory.getObject();
                            }
                        }, acc);
                }catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }else {
                object = factory.getObject();
            }
        }catch (FactoryBeanNotInitializedException ex) {
            throw new BeanCurrentlyInCreationException(beanName, ex.toString());
        }catch (Throwable ex) {
            throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
        }

        // 如果结果object此时还是null,并且这个FactoryBean还是在创建的这个过程中,则
        // 抛出异常,此时说明初始化流程是存在问题的
        if (object == null && isSingletonCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(
                    beanName, "FactoryBean which is currently in creation returned null from getObject");
        }
        return object;
    }

这段代码是也是段纸老虎代码,看着很长,其实很简单,就是调用了FactoryBean的getObject方法而已,我们再来看代码块16的if中调用的代码,注意真正被调用的方法在AbstractAutowireCapableBeanFactory中:

                                                            代码块18
        @Override
    protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
        return applyBeanPostProcessorsAfterInitialization(object, beanName);
    }

    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {
        // 执行所有BeanPostProcessor的postProcessAfterInitialization方法
        Object result = existingBean;
        // 遍历执行
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessAfterInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }

至此,代码块10中的3处就完了,是不是感觉费了很久功夫呢?其实阅读源码就是这样,方法中套方法,经常都是你看完了一个很长的方法,再回到原来的方法,发现其实只是这个方法中的一行代码,我早些时候经常都是边看边吐血,因为真的太难了,不过好在一遍又一遍的坚持了下来,完了还是很开心的。

代码块10.4

小小的吐槽完了,继续看代码块10中的第4处,这里主要是针对prototype的循环依赖检查,这个是当A中有B,B中有A并且A和B的scope都是prototype的时候会在这里抛异常,spring解决不了prototype的循环依赖,原因也简单,你想嘛,你想要一个新的A,创建A的时候发现A需要一个新的B,所以要去创建B,但是创建B的时候,又要一个新的A,然后就陷入无限循环,最后要么StackOverFlowException,要么OutOfMemoryError,所以spring就在这里直接抛异常了。

代码块10.5

接下来是代码块10的第5处调用的方法,这个方法是用来获取bean的原始名称的:

                                                            代码块19
        protected String originalBeanName(String name) {
        String beanName = transformedBeanName(name);
        // 如果name中有"&",那就给beanName也加上“&”
        // 因为transformedBeanName中去掉了“&”
        if (name.startsWith(FACTORY_BEAN_PREFIX)) {
            beanName = FACTORY_BEAN_PREFIX + beanName;
        }
        return beanName;
    }

第一行的代码解释见代码块5,剩下的很简单了,我们继续代码块10中的第6处调用的方法:

代码块10.6

                                                            代码块20
        protected void markBeanAsCreated(String beanName) {
        // alreadyCreated 是已经创建的和正准备去创建的集合
        if (!this.alreadyCreated.contains(beanName)) {
            this.alreadyCreated.add(beanName);
        }
    }

依然是个很简单的方法,代码块10中第6处调用这个方法,是因为准备去创建这个bean了。我们继续代码块10中第7处,这下要讲这个之前代码块12和代码块2中跳过的getMergedLocalBeanDefinition(String name)方法了,我们先贴出来这个方法的代码哈:

代码块10.7

                                                            代码块21
    // 首先调用的方法
    protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
        // 看看缓存中有没有,如果有的话直接返回
        RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
        if (mbd != null) {
            return mbd;
        }
        // 调用下面的方法
        return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
    }

    protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
            throws BeanDefinitionStoreException {
        // 继续调用下面的方法
        return getMergedBeanDefinition(beanName, bd, null);
    }

    protected RootBeanDefinition getMergedBeanDefinition(
            String beanName, BeanDefinition bd, BeanDefinition containingBd) throws BeanDefinitionStoreException {
        // 加锁防止并发
        synchronized (this.mergedBeanDefinitions) {
            // 这个是返回结果
            RootBeanDefinition mbd = null;

            // Check with full lock now in order to enforce the same merged instance.
            // 之所以还在这里get一下,是因为防止从上面的方法到这里的时候已经有别的线程把这个RootBeanDefinition创建好了
            // 现在在这个串行的操作中,如果没有get到,说明就是确实还没有
            if (containingBd == null) {
                mbd = this.mergedBeanDefinitions.get(beanName);
            }
            // 若不存在于缓存中,则进行下一步操作
            if (mbd == null) {
                if (bd.getParentName() == null) {
                    // 如果没有父定义的BeanDefinition,则不需要合并,直接通过深克隆的方式
                    // 创建RootBeanDefinition
                    if (bd instanceof RootBeanDefinition) {
                        mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                    } else {
                        mbd = new RootBeanDefinition(bd);
                    }
                } else {
                    // 存在父定义BeanDefinition,递归着去和父定义的合并
                    BeanDefinition pbd;
                    try {
                        // 获取父BeanDefinition真正的名称
                        String parentBeanName = transformedBeanName(bd.getParentName());
                        if (!beanName.equals(parentBeanName)) {
                            // 递归调用
                            pbd = getMergedBeanDefinition(parentBeanName);
                        } else {
                            if (getParentBeanFactory() instanceof ConfigurableBeanFactory) {
                                // 强转再递归调用
                                pbd = ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(parentBeanName);
                            } else {
                                throw new NoSuchBeanDefinitionException(bd.getParentName(),
                                        "Parent name '" + bd.getParentName() + "' is equal to bean name '" + beanName +
                                        "': cannot be resolved without an AbstractBeanFactory parent");
                            }
                        }
                    } catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                                "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
                    }
                    // 根据父定义深度拷贝一个新的
                    mbd = new RootBeanDefinition(pbd);
                    // 用子覆盖父
                    mbd.overrideFrom(bd);
                }

                // 默认单例
                if (!StringUtils.hasLength(mbd.getScope())) {
                    mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
                }
                // 设置scope,此时containingBd还是null
                if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
                    mbd.setScope(containingBd.getScope());
                }
                // containingBd是null && this.cacheBeanMetadata && 该bean是否可以被缓存
                // 这里这三个条件走到这块一般都成立了
                if (containingBd == null && isCacheBeanMetadata() && isBeanEligibleForMetadataCaching(beanName)) {
                    this.mergedBeanDefinitions.put(beanName, mbd);
                }
            }

            return mbd;
        }
    }

这个方法的代码不算难,但是为什么要把其他类型的BeanDefinition都转成RootBeanDefinition呢?因为RootBeanDefinition是被spring作为在运行时候的统一使用的BeanDefnition(即在创建bean实例时候使用的统一的BeanDefnition),里面还包含了解析过的构造方法缓存,方法参数缓存其他缓存信息,如果说其他类型的BeanDefnition都是用于把元数据(就是如xml或者注解)表达为spring可以认识的信息的话,那么RootBeanDefinition就是把spring已经认识出来的信息表达为了可以实际去使用的信息。

我们继续看代码块10中第8处方法调用的方法:

代码块10.8

                                                                代码块22
        protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, Object[] args)
            throws BeanDefinitionStoreException {

        // 如果是抽象则抛出异常
        if (mbd.isAbstract()) {
            throw new BeanIsAbstractException(beanName);
        }

        // 如果args不是null但是beanDefinition对应的类型却不是prototype,则抛出异常
        // 这个是因为当args不是null的时候,代表需要动态参数实例化bean,而此时该bean的作用域只能是prototype
        if (args != null && !mbd.isPrototype()) {
            throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
                    "Can only specify arguments for the getBean method when referring to a prototype bean definition");
        }
    }

代码块22我没有标数字,我稍微解释一下这里面的第二处注释,方法参数args不为null的情况是当你调用了applicationContext中带参数的getbean方法或者是beanFactory中带参数的getbean方法时候,这里才不是null,但是高版本的spring已经把这个对参数检查去掉了。

代码块10.9

继续看代码块10中第9处,此时已经找到我们这个beanName对应的bean需要依赖的bean是哪些bean了,因此将依赖关系注册进去:

                                                                代码块23
    public void registerDependentBean(String beanName, String dependentBeanName) {
        // 获取真正的bean名称
        String canonicalName = canonicalName(beanName);
        // 这段代码是将beanName和dependentBeanName的依赖关系注册到dependentBeanMap中
        // 注意这个是beanName依赖dependentBeanName
        synchronized (this.dependentBeanMap) {
            Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
            if (dependentBeans == null) {
                dependentBeans = new LinkedHashSet<String>(8);
                this.dependentBeanMap.put(canonicalName, dependentBeans);
            }
            dependentBeans.add(dependentBeanName);
        }

        // 这段代码是将beanName和dependentBeanName的依赖关系注册到dependentBeanMap中
        // 注意这个是dependentBeanName依赖beanName,关系是反着的
        // 就是说当A中有B,B中有A和C的时候,C中又有A,spring通过这两个map就能知道
        // A依赖了B,而依赖A的有A和C
        synchronized (this.dependenciesForBeanMap) {
            Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName);
            if (dependenciesForBean == null) {
                dependenciesForBean = new LinkedHashSet<String>(8);
                this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);
            }
            dependenciesForBean.add(canonicalName);
        }
    }

里面第一行注释调用的方法在本篇的代码块7已经讲过,其他的都很容易理解了,我们继续回过头来看代码块10中的第10处,在看这里调用的getSingleton方法之前,你需要注意到这个getSingleton方法和之前的不一样,此外,这个方法调用的时候所传的第二参数是个实现了ObjectFactory的匿名内部类,并且在它的实现里面调用了createBean方法,限于篇幅,createBean方法会在下一篇讲,不然估计你可能会晕的更厉害。我们来看这里的getSingleton方法,注意这个getSingleton和上面代码块8的不是一个方法:

代码块10.10

                                                                代码块24
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "'beanName' must not be null");
        synchronized (this.singletonObjects) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                // 如果当前beanFactory处在destruction状态中,则不允许创建bean
                // 这个状态指的是beanFactory执行了destroySingletons方法,即applicationContext执行close方法会调用到这个方法
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,
                            "Singleton bean creation not allowed while the 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 + "'");
                }
                // 1. 创建单例前的检查
                beforeSingletonCreation(beanName);
                // suppressedExceptions用户记录在创建期间出现的异常
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<Exception>();
                }
                try {
                    // 调用ObjectFactory来创建bean
                    singletonObject = singletonFactory.getObject();
                }catch (BeanCreationException ex) {
                    if (recordSuppressedExceptions) {
                        for (Exception suppressedException : this.suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                    throw ex;
                }finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    // 2. 创建单例后的检查
                    afterSingletonCreation(beanName);
                }
                // 将创建出来的bean放到缓存中
                addSingleton(beanName, singletonObject);
            }
            return (singletonObject != NULL_OBJECT ? singletonObject : null);
        }
    }

我们来看上面的代码块中1,创建单例前的检查:

                                                                代码块25
        protected void beforeSingletonCreation(String beanName) {
        // 检查bean是否要包含在检查已经创建的集合中,如果不是,则看bean是否在创建中
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    }

然后是代码块24中的2,创建单例后的检查:

                                                                代码块26
        protected void afterSingletonCreation(String beanName) {
        // 检查bean是否要包含在检查已经创建的集合中,如果不是,则从正在创建的集合中移除,
        // 移除失败则抛异常
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
            throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
        }
    }

getSingleton方法完了,我们继续回到代码块10看11处的创建prototype前的检查:

代码块10.11

                                                                代码块27
        @SuppressWarnings("unchecked")
    protected void beforePrototypeCreation(String beanName) {
        // 从当前线程正在创建的prototype中拿所有的正在创建的集合
        Object curVal = this.prototypesCurrentlyInCreation.get();
        // 如果curlVal是空,则设置当前bean为正在创建的bean
        if (curVal == null) {
            this.prototypesCurrentlyInCreation.set(beanName);
        // 如果不是空并且是个String(代表有一个在创建中),则创建集合,并且把curVal
        // 和当前beanName都加进去
        } else if (curVal instanceof String) {
            Set<String> beanNameSet = new HashSet<String>(2);
            beanNameSet.add((String) curVal);
            beanNameSet.add(beanName);
            this.prototypesCurrentlyInCreation.set(beanNameSet);
        // 这种的说明是有两个以上的在创建,直接加入正在创建的集合中去
        } else {
            Set<String> beanNameSet = (Set<String>) curVal;
            beanNameSet.add(beanName);
        }
    }

接下来是代码块10看12处:

代码块10.12

                                                                代码块29
        @SuppressWarnings("unchecked")
    protected void afterPrototypeCreation(String beanName) {
        // 获取正在创建的prototype的集合
        Object curVal = this.prototypesCurrentlyInCreation.get();
        // 如果是String则直接remove掉
        if (curVal instanceof String) {
            this.prototypesCurrentlyInCreation.remove();
        }
        // 如果是set则从set中删除
        else if (curVal instanceof Set) {
            Set<String> beanNameSet = (Set<String>) curVal;
            beanNameSet.remove(beanName);
            if (beanNameSet.isEmpty()) {
                this.prototypesCurrentlyInCreation.remove();
            }
        }
    }

至此doGetBean方法已经讲完,下一篇,我们开始createBean方法

赞(1) 打赏
版权归原创作者所有,任何形式转载请联系作者;码农code之路 » 深入理解Spring IOC(四)、 实例化开启

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏