由于源码会大量用到类型匹配,例如 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
这个小知识的介绍就到这里
欢迎关注,学习不迷路!