9. Spring源码篇之类型匹配isTypeMatch

简介

由于源码会大量用到类型匹配,例如 beanFactory.getBeanNamesForType里面就需要要到,所有先了解下匹配的原理,后续源码分析就轻松些

这也是spring提供的一个工具方法,我们也可以使用

源码分析

源码中有大量的 FactoryBean 判断,前面我们分析过FactoryBean知道其原理,那么FactoryBean的分支判断就可以不必看了,下面源码是省略了FactoryBean

源码如下

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

    // &name->name
    String beanName = transformedBeanName(name);
    
    // 看单例池中是否有这个Bean,有的内置Bean是一开始就在单例池中
    Object beanInstance = getSingleton(beanName, false);
    
    if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
        // 直接匹配 就是使用的Class.isAssignableFrom去判断的
        if (typeToMatch.isInstance(beanInstance)) {
            return true;
        }
        return false;
    } else if (containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
        // 连Beandifinition都没有,直接返回false
        return false;
    }


    // 从单例池中没有获取Bean,通过BeanDefinition去判断
    RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();

    Class<?> classToMatch = typeToMatch.resolve();
  
    Class<?>[] typesToMatch = (FactoryBean.class == classToMatch ?
            new Class<?>[]{classToMatch} : new Class<?>[]{FactoryBean.class, classToMatch});


    Class<?> predictedType = null;

    if (predictedType == null) {
        // 通过beanName去获取Class,通过Class.forName去获取Class但是不实例化
        predictedType = predictBeanType(beanName, mbd, typesToMatch);
        if (predictedType == null) {
            return false;
        }
    }

    ResolvableType beanType = null;

    // 有targetType的情况
    if (beanType == null) {
        ResolvableType definedType = mbd.targetType;
        if (definedType == null) {
            definedType = mbd.factoryMethodReturnType;
        }
        if (definedType != null && definedType.resolve() == predictedType) {
            beanType = definedType;
        }
    }

    if (beanType != null) {
        return typeToMatch.isAssignableFrom(beanType);
    }

    // 通过isAssignableFrom判断返回
    return typeToMatch.isAssignableFrom(predictedType);
}

通过源码分析可以知道,类型匹配的原理其实最终就是用的 Class.isAssignableFrom 去判断,如果单例池中有对象,那么就使用
beanInstance.getClass拿到Class,如果没有就通过BeanDefinition使用Class.forName拿到Class但不实例化

使用

public interface UserGenerics {

}

@Component
public class UserBean implements UserGenerics {

}

public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

    System.out.println(context.isTypeMatch("userBean", UserGenerics.class));
}


输出 true

这个小知识的介绍就到这里


欢迎关注,学习不迷路!

你可能感兴趣的:(spring,framework,spring,java,后端)