天天看点

Spring源码解析 - FactoryBean&&BeanFactory(下)

@Override
    public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
        if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
            return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
        }
        // 先从缓存获取
        Map<Class<?>, String[]> cache =
                (includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
        String[] resolvedBeanNames = cache.get(type);
        if (resolvedBeanNames != null) {
            return resolvedBeanNames;
        }
        // 调用doGetBeanNamesForType获取beanName
        resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
        // 所传入类能否被当前类加载所加载
        if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
            // 放到缓存,解析一次后从缓存中获取
            // 这里对应到我们这里 K:FactoryBeanService,V:beanFactoryLearn
            cache.put(type, resolvedBeanNames);
        }
        return resolvedBeanNames;
    }      

doGetBeanNamesForType

private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
        List<String> result = new ArrayList<>();

        // 循环所有beanName,这个是在Spring容器启动解析Bean的时候放入到这个List中的
        // 校验所有 bean definitions
        for (String beanName : this.beanDefinitionNames) {
            // Only consider bean as eligible if the bean name is not defined as alias for some other bean.
            // 如果未将 bean name 定义为其他bean的别名,则仅将bean视为可选
            if (!isAlias(beanName)) {
                try {
                    // 根据 beanName 获取 RootBeanDefinition
                    RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                    // Only check bean definition if it is complete.
                    // RootBeanDefinition 的 Bean 不是抽象类、非延迟初始化
                    if (!mbd.isAbstract() && (allowEagerInit ||
                            (mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
                                    !requiresEagerInitForType(mbd.getFactoryBeanName()))) {
                        // 是否为 FactoryBean 的子类
                        boolean isFactoryBean = isFactoryBean(beanName, mbd);
                        BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
                        boolean matchFound = false;
                        boolean allowFactoryBeanInit = (allowEagerInit || containsSingleton(beanName));
                        boolean isNonLazyDecorated = (dbd != null && !mbd.isLazyInit());
                        if (!isFactoryBean) {
                            if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
                                // 如果isTypeMatch返回true,则把这个beanName即 factoryBeanLearn 放入到result中返回
                                matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                            }
                        }
                        else  {
                            if (includeNonSingletons || isNonLazyDecorated ||
                                    (allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {
                                matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                            }
                            if (!matchFound) {
                                // 如果不匹配,还是FactoryBean的子类 这里会把beanName变为 &beanName
                                // In case of FactoryBean, try to match FactoryBean instance itself next.
                                beanName = FACTORY_BEAN_PREFIX + beanName;
                                matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                            }
                        }
                        if (matchFound) {
                            result.add(beanName);
                        }
                    }
                }
                catch (CannotLoadBeanClassException | BeanDefinitionStoreException ex) {
                    if (allowEagerInit) {
                        throw ex;
                    }
                    // Probably a placeholder: let's ignore it for type matching purposes.
                    LogMessage message = (ex instanceof CannotLoadBeanClassException ?
                            LogMessage.format("Ignoring bean class loading failure for bean '%s'", beanName) :
                            LogMessage.format("Ignoring unresolvable metadata in bean definition '%s'", beanName));
                    logger.trace(message, ex);
                    // Register exception, in case the bean was accidentally unresolvable.
                    onSuppressedException(ex);
                }
            }
        }

        // 这里的Bean是Spring容器创建的特殊的几种Bean ,如Environment
        // Check manually registered singletons too.
        for (String beanName : this.manualSingletonNames) {
            try {
                // In case of FactoryBean, match object created by FactoryBean.
                if (isFactoryBean(beanName)) {
                    if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
                        result.add(beanName);
                        // Match found for this bean: do not match FactoryBean itself anymore.
                        continue;
                    }
                    // In case of FactoryBean, try to match FactoryBean itself next.
                    beanName = FACTORY_BEAN_PREFIX + beanName;
                }
                // Match raw bean instance (might be raw FactoryBean).
                if (isTypeMatch(beanName, type)) {
                    result.add(beanName);
                }
            }
            catch (NoSuchBeanDefinitionException ex) {
                // Shouldn't happen - probably a result of circular reference resolution...
                logger.trace(LogMessage.format(
                        "Failed to check manually registered singleton with name '%s'", beanName), ex);
            }
        }

        return StringUtils.toStringArray(result);
    }      

FactoryBeanLearn是FactoryBean类型的,所以上面代码中会调用isTypeMatch判断FactoryBeanLearn是不是和传入类型匹配。这里是值:FactoryBeanService类。

isTypeMatch

类型匹配判断

protected boolean isTypeMatch(String name, ResolvableType typeToMatch, boolean allowFactoryBeanInit)
            throws NoSuchBeanDefinitionException {

        // 转换beanName,我们的beanName为factoryBeanLearn 因为上面循环了Spring容器中的所有的Bean
        String beanName = transformedBeanName(name);
        boolean isFactoryDereference = BeanFactoryUtils.isFactoryDereference(name);

        // 因为我们这里是用的AbstractApplicationContext的子类从Spring容器获取Bean
        // 获取beanName为factoryBeanLearn的Bean实例,这里是可以获取到Bean实例的
        // Check manually registered singletons.
        Object beanInstance = getSingleton(beanName, false);
        if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
            // factoryBeanLearn是FactoryBean的实现类
            if (beanInstance instanceof FactoryBean) {
                // 判断beanName是不是&开头,这里明显不是
                if (!isFactoryDereference) {
                    // 从factoryBeanLearn中获取type类型
                    Class<?> type = getTypeForFactoryBean((FactoryBean<?>) beanInstance);
                    // 从factoryBeanLearn中获取到的type类型和传入类型是否一致,是则返回
                    return (type != null && typeToMatch.isAssignableFrom(type));
                }
            
            ...      

getTypeForFactoryBean

@Nullable
    protected Class<?> getTypeForFactoryBean(FactoryBean<?> factoryBean) {
        try {
            if (System.getSecurityManager() != null) {
                return AccessController.doPrivileged(
                        (PrivilegedAction<Class<?>>) factoryBean::getObjectType, getAccessControlContext());
            }
            else {
                // 调用FactoryBean实例的getObjectType()方法
                return factoryBean.getObjectType();
            }
        }
        catch (Throwable ex) {
            // Thrown from the FactoryBean's getObjectType implementation.
            logger.info("FactoryBean threw exception from getObjectType, despite the contract saying " +
                    "that it should return null if the type of its object cannot be determined yet", ex);
            return null;
        }
    }      

在调用factoryBeanLearn的getObjectType方法时,获取到的值为:com.javaedge.FactoryBeanService和我们传入type是一样的类型。所以这里返回true,根据我们上面说的如果isTypeMatch返回true的话,我们返回的beanName为factoryBeanLearn。

调用getBean(Class requiredType)方法根据类型获取容器中bean时

对应例子就是:根据类型FactoryBeanService从Spring容器中获取Bean(Spring容器中没有FactoryBeanService类型的BeanDefinition,但有一个Bean和FactoryBeanService这个类型有一些关系)。

Spring在根据type去获取Bean的时候,会先获取到beanName。

获取beanName的过程

先循环Spring容器中的所有的beanName

然后根据beanName获取对应的BeanDefinition,如果当前bean是FactoryBean的类型,则会从Spring容器中根据beanName获取对应的Bean实例,接着调用获取到的Bean实例的getObjectType方法获取到Class类型,判断此Class类型和我们传入的Class是否是同一类型。如果是则返回测beanName,对应到我们这里就是:根据factoryBeanLearn获取到FactoryBeanLearn实例,调用FactoryBeanLearn的getObjectType方法获取到返回值FactoryBeanService.class。和我们传入的类型一致,所以这里获取的beanName为factoryBeanLearn。

换句话说这里我们把factoryBeanLearn这个beanName映射为了:FactoryBeanService类型。即FactoryBeanService类型对应的beanName为factoryBeanLearn这是很重要的一点。