当前位置: 代码迷 >> 综合 >> spring启动流程探索四、refresh()(3)getBeanNamesForType-isTypeMatch
  详细解决方案

spring启动流程探索四、refresh()(3)getBeanNamesForType-isTypeMatch

热度:80   发布时间:2023-11-26 12:05:14.0

spring探索第四节

  • getBeanNamesForType
  • isTypeMatch(beanName, type, allowFactoryBeanInit)

getBeanNamesForType

这个方法其实讲起来还挺复杂的,因为他里面调用很多的其他方法,而那些其他的方法内容也很繁琐,所以我先大家定个主题,我们在这只探讨和上个章节展开一致的内容,是沿着我们refresh的流程往下走的,所以如果大家在看的时候要明确。上代码:

beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
@Overridepublic String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
    // 跟着调用链过来,就可以发现我们allowEagerInit为false,所以要走的是doGetBeanNamesForType这个方法if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
    return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);}// 这里是根据是否包含空单例这个标识includeNonSingletons 拿缓存Map<Class<?>, String[]> cache =(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);// 如果缓存中有,直接返回String[] resolvedBeanNames = cache.get(type);if (resolvedBeanNames != null) {
    return resolvedBeanNames;}resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
    cache.put(type, resolvedBeanNames);}return resolvedBeanNames;}

看了这个方法,然后根据我们调用链传进的参数,我们大概就知道要走的方法是

 doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit)

在这里大家要记得一个事情,type是用ResolvableType.forRawClass包装了下

public static ResolvableType forRawClass(@Nullable Class<?> clazz) {
    return new ResolvableType(clazz) {
    @Overridepublic ResolvableType[] getGenerics() {
    return EMPTY_TYPES_ARRAY;}@Overridepublic boolean isAssignableFrom(Class<?> other) {
    return (clazz == null || ClassUtils.isAssignable(clazz, other));}@Overridepublic boolean isAssignableFrom(ResolvableType other) {
    Class<?> otherClass = other.resolve();return (otherClass != null && (clazz == null || ClassUtils.isAssignable(clazz, otherClass)));}};}

然后包装的时候重写了三个方法,这重写的三个方法在isTypeMatch方法中将会用到

private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
    List<String> result = new ArrayList<>();// Check all 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.// 非别名的beanName可以进入if (!isAlias(beanName)) {
    try {
    // 获取合并的定义信息,这里合并bean定义信息的方法也是很复杂的,但是这个不影响主线,//所以不展开细讲,这个主要作用是去判断他是否有父定义信息,有的话就合并。RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// Only check bean definition if it is complete.// 检查定义信息是否完整if (!mbd.isAbstract() && (allowEagerInit ||(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
    // 判断bean是不是FactoryBeanboolean 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)) {
    								//检查bean是否是type的子类matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);}}else  {
    if (includeNonSingletons || isNonLazyDecorated ||(allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {
    matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);}if (!matchFound) {
    // In case of FactoryBean, try to match FactoryBean// instance itself next.//如果是FactoryBean,请尝试接下来匹配FactoryBean实例本身。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);}}}// Check manually registered singletons too.// 检查下手动注入的for (String beanName : this.manualSingletonNames) {
    try {
    // In case of FactoryBean, match object created by FactoryBean.// 判断是否是FactoryBean 子类if (isFactoryBean(beanName)) {
    if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
    // 找到就不匹配FactoryBeanresult.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).// 匹配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);}

看了下,整个代码流程,基本上可以概况成这样:
去循环beanDefinitionNames,然后拿到每一个bean的定义信息,然后检查定义信息是否完整,
定义信息完整的话,就再判断bean是否是FactoryBean子类,再接着就是调用isTypeMatch方法判断bean是否和type相符,其实就是判断bean是否实现了type,找到了就加到result中。
然后再去循环手动创建的单例(manualSingletonNames)也是去调用isTypeMatch去判断。
大体逻辑上就是这样,而相信大家在其中看到isTypeMatch这个方法被频繁用到,所以我们接下来单独讲解下这个方法。

isTypeMatch(beanName, type, allowFactoryBeanInit)

protected boolean isTypeMatch(String name, ResolvableType typeToMatch, boolean allowFactoryBeanInit)throws NoSuchBeanDefinitionException {
    // 获取转换后的beanNameString beanName = transformedBeanName(name);// 判断是否为FactoryDereferenceboolean isFactoryDereference = BeanFactoryUtils.isFactoryDereference(name);// Check manually registered singletons.// 拿单例Object beanInstance = getSingleton(beanName, false);if (beanInstance != null && beanInstance.getClass() != NullBean.class) {
    if (beanInstance instanceof FactoryBean) {
    // 不是工厂取消引用if (!isFactoryDereference) {
    //拿beanInstance工厂类类型Class<?> type = getTypeForFactoryBean((FactoryBean<?>) beanInstance);// 这里的typeToMatch是重写后的,所以调用他的重写方法//所以这样判断type是不是typeToMatch里面clazz的实现类return (type != null && typeToMatch.isAssignableFrom(type));}else {
    // 判断是不是拿到的实例是不是typeToMatch里面clazz的实现类return typeToMatch.isInstance(beanInstance);}}else if (!isFactoryDereference) {
    if (typeToMatch.isInstance(beanInstance)) {
    // Direct match for exposed instance?return true;}// 这样也是调用重写后的方法// 判断EMPTY_TYPES_ARRAY的大小(不走这条路)else if (typeToMatch.hasGenerics() && containsBeanDefinition(beanName)) {
    // Generics potentially only match on the target class, not on the proxy...RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);Class<?> targetType = mbd.getTargetType();if (targetType != null && targetType != ClassUtils.getUserClass(beanInstance)) {
    // Check raw class match as well, making sure it's exposed on the proxy.Class<?> classToMatch = typeToMatch.resolve();// 拿classToMatch 的clazzif (classToMatch != null && !classToMatch.isInstance(beanInstance)) {
    return false;}// 如果targetType是typeToMatch实现类if (typeToMatch.isAssignableFrom(targetType)) {
    return true;}}ResolvableType resolvableType = mbd.targetType;if (resolvableType == null) {
    resolvableType = mbd.factoryMethodReturnType;}return (resolvableType != null && typeToMatch.isAssignableFrom(resolvableType));}}return false;}else if (containsSingleton(beanName) && !containsBeanDefinition(beanName)) {
    // null instance registeredreturn false;}// No singleton instance found -> check bean definition.// 没拿到单例,去拿定义信息BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    // No bean definition found in this factory -> delegate to parent.//没有找到定义信息就去parent里面找return parentBeanFactory.isTypeMatch(originalBeanName(name), typeToMatch);}// Retrieve corresponding bean definition.// 拿合并定义信息RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();// Setup the types that we want to match against// 设置我们需要匹配的类型Class<?> classToMatch = typeToMatch.resolve();if (classToMatch == null) {
    classToMatch = FactoryBean.class;}Class<?>[] typesToMatch = (FactoryBean.class == classToMatch ?new Class<?>[] {
    classToMatch} : new Class<?>[] {
    FactoryBean.class, classToMatch});// Attempt to predict the bean type// 先预测下类型Class<?> predictedType = null;// We're looking for a regular reference but we're a factory bean that has// a decorated bean definition. The target bean should be the same type// as FactoryBean would ultimately return.// 不是是非取消引用,并且beanName是FactoryBeanif (!isFactoryDereference && dbd != null && isFactoryBean(beanName, mbd)) {
    // We should only attempt if the user explicitly set lazy-init to true// and we know the merged bean definition is for a factory bean.// 非懒加载if (!mbd.isLazyInit() || allowFactoryBeanInit) {
    RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd);// 拿到预测类型Class<?> targetType = predictBeanType(dbd.getBeanName(), tbd, typesToMatch);// 预测类型不是工厂beanif (targetType != null && !FactoryBean.class.isAssignableFrom(targetType)) {
    predictedType = targetType;}}}// If we couldn't use the target type, try regular prediction.// 常规预测(如果predictedType 为null)if (predictedType == null) {
    predictedType = predictBeanType(beanName, mbd, typesToMatch);if (predictedType == null) {
    return false;}}// Attempt to get the actual ResolvableType for the bean.// 现在开始拿bean的实际beanTypeResolvableType beanType = null;// If it's a FactoryBean, we want to look at what it creates, not the factory class.// 如果预测类型是FactoryBeanif (FactoryBean.class.isAssignableFrom(predictedType)) {
    if (beanInstance == null && !isFactoryDereference) {
    // 拿他的FactoryBean类型beanType = getTypeForFactoryBean(beanName, mbd, allowFactoryBeanInit);predictedType = beanType.resolve();if (predictedType == null) {
    return false;}}}// 取消引用-》SmartInstantiationAwareBeanPostProcessor 这是个特例,为了兼容else if (isFactoryDereference) {
    // Special case: A SmartInstantiationAwareBeanPostProcessor returned a non-FactoryBean// type but we nevertheless are being asked to dereference a FactoryBean...// Let's check the original bean class and proceed with it if it is a FactoryBean.predictedType = predictBeanType(beanName, mbd, FactoryBean.class);if (predictedType == null || !FactoryBean.class.isAssignableFrom(predictedType)) {
    return false;}}// We don't have an exact type but if bean definition target type or the factory// method return type matches the predicted type then we can use that.// 如果没拿到beanTypeif (beanType == null) {
    ResolvableType definedType = mbd.targetType;if (definedType == null) {
    definedType = mbd.factoryMethodReturnType;}if (definedType != null && definedType.resolve() == predictedType) {
    beanType = definedType;}}// If we have a bean type use it so that generics are considered// 拿到实际的beanType直接判断返回if (beanType != null) {
    return typeToMatch.isAssignableFrom(beanType);}// 没拿到就返回预测的return typeToMatch.isAssignableFrom(predictedType);}

我们现在来整理下isTypeMatch的逻辑
1,首先去拿单例,拿到了就去判断类型,看看是不是typeToMatch中的子类,直接判断返回
2.没拿到单例,就去检查定义信息,定义信息查不到就去查parent
3.接下来就开始预测bean的类型(predictedType),如果bean是是factorybean,那就根据factorybean预测,不是的话就常规预测
4.预测完了,开始拿bean的实际类型,如果预测类型(predictedType)是factorybean,那我就先去试着去拿下bean 的工厂实际类型,拿到了就赋值给predictedType
5.如果预测类型(predictedType)不是factorybean就去拿定义中的targetType或者factoryMethodReturnType
6.如果能拿到实际类型,就根据实际类型进行类型判断,拿不到就根据预测类型判断。

这里就大略清楚了getBeanNamesForType和isTypeMatch的作用了。其实这里面还有些关键点没讲,我们做个备忘,如果有小伙伴觉得需要讲讲,我就单独开个章节去讲讲。

  相关解决方案