Spring 依赖注入[3]

267 阅读6分钟

「这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战

resolveDependency

  • DependencyDescriptor:依赖描述
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
      @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    //初始化参数名称发现器
   descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
    
    //就是1.8中的Optional(方法参数是这个)
   if (Optional.class == descriptor.getDependencyType()) {
      return createOptionalDependency(descriptor, requestingBeanName);
   }
    
    //是
   else if (ObjectFactory.class == descriptor.getDependencyType() ||
         ObjectProvider.class == descriptor.getDependencyType()) {
      return new DependencyObjectProvider(descriptor, requestingBeanName);
   }
   else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
      return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
   }
   else {
      Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
            descriptor, requestingBeanName);
      if (result == null) {
         result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
      }
      return result;
   }
}
初始化参数名称获取器
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
​
//get获取的是这个对象
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
​
    public DefaultParameterNameDiscoverer() {
        if (KotlinDetector.isKotlinReflectPresent() && !NativeDetector.inNativeImage()) {
            addDiscoverer(new KotlinReflectionParameterNameDiscoverer());
        }
        //默认的反射获取器
        addDiscoverer(new StandardReflectionParameterNameDiscoverer());
        //本地变量表
        addDiscoverer(new LocalVariableTableParameterNameDiscoverer());
    }

在jdk1.7(反射不可以)和1.8(需要配参数)中很难获取参数的变量名称,因此这里需要标准的反射和本地变量表(作为备用)。

正常处理
else {
    //注意:这里有个lazy,就是判断属性或方法参数有@Lazy注解,如果有则生成实现懒加载代理对象并返回(使用到的时候才创建);如果没有lazy注解则result=null
   Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
         descriptor, requestingBeanName);
   if (result == null) {
      result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
   }
   return result;
}
@Lazy相关
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
      descriptor, requestingBeanName);
      
public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, @Nullable String beanName) {
        return (isLazy(descriptor) ? buildLazyResolutionProxy(descriptor, beanName) : null);
    }
    
        protected Object buildLazyResolutionProxy(final DependencyDescriptor descriptor, final @Nullable String beanName) {
        BeanFactory beanFactory = getBeanFactory();
        Assert.state(beanFactory instanceof DefaultListableBeanFactory,
                "BeanFactory needs to be a DefaultListableBeanFactory");
        final DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) beanFactory;
​
        TargetSource ts = new TargetSource() {
            @Override
            public Class<?> getTargetClass() {
                return descriptor.getDependencyType();
            }
            @Override
            public boolean isStatic() {
                return false;
            }
           
            @Override
            public Object getTarget() {
                Set<String> autowiredBeanNames = (beanName != null ? new LinkedHashSet<>(1) : null);
                Object target = dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null);
                if (target == null) {
                    Class<?> type = getTargetClass();
                    if (Map.class == type) {
                        return Collections.emptyMap();
                    }
                    else if (List.class == type) {
                        return Collections.emptyList();
                    }
                    else if (Set.class == type || Collection.class == type) {
                        return Collections.emptySet();
                    }
                    throw new NoSuchBeanDefinitionException(descriptor.getResolvableType(),
                            "Optional dependency not present for lazy injection point");
                }
                if (autowiredBeanNames != null) {
                    for (String autowiredBeanName : autowiredBeanNames) {
                        if (dlbf.containsBean(autowiredBeanName)) {
                            dlbf.registerDependentBean(autowiredBeanName, beanName);
                        }
                    }
                }
                return target;
            }
            @Override
            public void releaseTarget(Object target) {
            }
        };
​
        ProxyFactory pf = new ProxyFactory();
        pf.setTargetSource(ts);
        Class<?> dependencyType = descriptor.getDependencyType();
        if (dependencyType.isInterface()) {
            pf.addInterface(dependencyType);
        }
        return pf.getProxy(dlbf.getBeanClassLoader());
    }

默认实现类是ContextAnnotationAutowireCandidateResolver,在这里会判断是否有lazy注解,如果有就返回一个针对Lazy的代理对象(这里和AOP有关系)。

  • 如果是包装的代理对象,那么在调用对象方法的时候,会首先调用getTarget方法获取Bean并调用方法。
doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
      @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
​
   InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
   try {
       //缓存相关,缓存里的其实是beanName,这里会通过beanname来获取bean实例,在单例中不会走到这里进来
       //为什么缓存的是名称?因为如果缓存的对象也是原型,那么也需要创建一个新的缓存类型对象
      Object shortcut = descriptor.resolveShortcut(this);
      if (shortcut != null) {
         return shortcut;
      }
​
       //处理@Value注解
      Class<?> type = descriptor.getDependencyType();
      Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
      if (value != null) {
         if (value instanceof String) {
             //占位符{}填充,从properties里取
            String strVal = resolveEmbeddedValue((String) value);
            BeanDefinition bd = (beanName != null && containsBean(beanName) ?
                  getMergedBeanDefinition(beanName) : null);
             //SPEL填充(#{}),这里会从Spring容器中获取bean  
            value = evaluateBeanDefinitionString(strVal, bd);
         }
          //类型转换器,将value转化为指定的类型
         TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
         try {
            return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
         }
         catch (UnsupportedOperationException ex) {
            // A custom TypeConverter which does not support TypeDescriptor resolution...
            return (descriptor.getField() != null ?
                  converter.convertIfNecessary(value, type, descriptor.getField()) :
                  converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
         }
      }
       
//这里对应的是没有通过@Value的情况
       // 这里是处理其他情况的,比如:@Autowired的是某个bean类型的容器(list/map等等,map的key必须是String)
       //如果是泛型,就会报错;如果是Object,就会把当前的所有bean都放进来
      Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
      if (multipleBeans != null) {
         return multipleBeans;
      }
//这里是获取bean
      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
       //如果获取到空,且是required= true,则抛异常
      if (matchingBeans.isEmpty()) {
         if (isRequired(descriptor)) {
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
         }
         return null;
      }
​
      String autowiredBeanName;
      Object instanceCandidate;
        //找到了多个
      if (matchingBeans.size() > 1) {
          //一一判断,byName就是这里实现的
         autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
         if (autowiredBeanName == null) {
             //没找到且require,也抛异常
            if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
               return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
            }
            else {
               // In case of an optional Collection/Map, silently ignore a non-unique case:
               // possibly it was meant to be an empty collection of multiple regular beans
               // (before 4.3 in particular when we didn't even look for collection beans).
               return null;
            }
         }
          //找到一个:那就赋值这个
         instanceCandidate = matchingBeans.get(autowiredBeanName);
      }
       //找到了一个就直接赋值
      else {
         // We have exactly one match.
         Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
         autowiredBeanName = entry.getKey();
         instanceCandidate = entry.getValue();
      }
​
      if (autowiredBeanNames != null) {
         autowiredBeanNames.add(autowiredBeanName);
      }
       //class的原因见下面,如果这里是class,那么需要创建对象
      if (instanceCandidate instanceof Class) {
         instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
      }
      Object result = instanceCandidate;
      if (result instanceof NullBean) {
         if (isRequired(descriptor)) {
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
         }
         result = null;
      }
      if (!ClassUtils.isAssignableValue(type, result)) {
         throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
      }
      return result;
   }
   finally {
      ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
   }
}
  • 占位符填充是从properties里取的,这个文件被封装到environment里了。

    • environment对象中包括properties文件,以及一些其他的变量,包括VMargs,系统变量等。
    • 需要在某些地方做@PropertySource()的注解,来指定和关联。
  • Nullbean:@Bean的方法返回的是个null,那么单例池中对应的bean就变成nullBean了。

findAutowireCandidates

根据上面的流程,可以得知这里的结果是很重要的,因此这个方法是这部分的一个核心点。

protected Map<String, Object> findAutowireCandidates(
      @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
    //根据bean类型,从本BF以及父BF中,返回所有符合的bean的名字
    //这里默认是从所有的bean(不只是单例)中获得bean名称
    //会从BF中的BD来获取
    //如果是factoryBean,则是通过factoryBean的getClass来判断类名
    //如果目前单例池中没有对应的bean对象,那么就从BD中来获取
   String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
         this, requiredType, true, descriptor.isEager());
   Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
    //和Spring启动有关,这个变量的写入在registerResolvableDependency方法
    //因此这里也算是一部分内容,获取bean名称+实例(或者class对象)
   for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
      Class<?> autowiringType = classObjectEntry.getKey();
      if (autowiringType.isAssignableFrom(requiredType)) {
         Object autowiringValue = classObjectEntry.getValue();
         autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
         if (requiredType.isInstance(autowiringValue)) {
            result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
            break;
         }
      }
   }
    //到这里就找到了所有符合的bean,这里做筛选
   for (String candidate : candidateNames) {
       //是否是自己,因此如果同个bean类型有多个,那么会先考虑注入别的bean对象,而非先考虑注入自身
       //如果不是自己,并且可以用来autowired,就会加到result里
      if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
         addCandidateEntry(result, candidate, descriptor, requiredType);
      }
   }
    //只有到result是空了,才会考虑是否需要对自己进行注入自己的bean
   if (result.isEmpty()) {
      boolean multiple = indicatesMultipleBeans(requiredType);
      // Consider fallback matches if the first pass failed to find anything...
      DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
      for (String candidate : candidateNames) {
          //这里的isAutowireCandidate,指的是@Bean是否指定了autowiredCandidate=true(默认是true),实际上是通过QualifierAnnotationAutowireCandidateResolver处理的,这里是责任链设计模式,包括:autowired的判断,以及根据bean的泛型判断
         if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
               (!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
            addCandidateEntry(result, candidate, descriptor, requiredType);
         }
      }
      if (result.isEmpty() && !multiple) {
         // Consider self references as a final pass...
         // but in the case of a dependency collection, not the very same bean itself.
         for (String candidate : candidateNames) {
            if (isSelfReference(beanName, candidate) &&
                  (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
                  isAutowireCandidate(candidate, fallbackDescriptor)) {
               addCandidateEntry(result, candidate, descriptor, requiredType);
            }
         }
      }
   }
   return result;
}
determineAutowireCandidate
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
   Class<?> requiredType = descriptor.getDependencyType();
    //判断某个bean有没有primary注解,有就返回那个primary的(这里是根据BD来判断的);但一组bean只能有一个@Primary,在这里会报错
   String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
   if (primaryCandidate != null) {
      return primaryCandidate;
   }
    //这里说明没有@Primary,那么这里会通过@Priority(int)来决定选哪个(int越小优先级越高),这个注解只能写在类上,不能写在方法上即不能和@Bean+方法的类型组合
   String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
   if (priorityCandidate != null) {
      return priorityCandidate;
   }
   // Fallback - 这里根据bean的名称来获取
   for (Map.Entry<String, Object> entry : candidates.entrySet()) {
      String candidateName = entry.getKey();
      Object beanInstance = entry.getValue();
      if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
            matchesBeanName(candidateName, descriptor.getDependencyName())) {
         return candidateName;
      }
   }
   return null;
}
  • 这里有一个问题:如果bean有了Primary或者priority的,那么其他优先级不高的可能就不会被用到。

    因此,在

    Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
    

    这一步骤中,如果创建了Object,value就是bean;如果没创建好,这里的value就是class对象。