Spring中@Autowired与@Resource自动注入实现原理

本文涉及的产品
云解析DNS,个人版 1个月
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: Spring中@Autowired与@Resource自动注入实现原理

关联博文

Spring后置处理器中的InstantiationAwareBeanPostProcessor详解

Spring中Bean实例化过程中的initializeBean方法

Spring中Bean实例化过程中的populateBean方法

Spring中@Autowired与@Resource自动注入实现原理

Spring中如何获取到一个Bean实例?


从autowiring使用上可以知道,这个autowiring属性在对Bean属性进行依赖注入时起作用。而这是在populateBean中实现的。也就是说,对属性autowiring的处理是populateBean的一部分。在前面我们分析Spring中Bean实例化过程中的populateBean方法可以看到自动注入的解析出现在两个部分。第一部分:

// AbstractAutowireCapableBeanFactory#populateBean
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
  MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
  // Add property values based on autowire by name if applicable.
  if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
    autowireByName(beanName, mbd, bw, newPvs);
  }
  // Add property values based on autowire by type if applicable.
  if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    autowireByType(beanName, mbd, bw, newPvs);
  }
  pvs = newPvs;
}

第二部分:

InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);


在第一部分为解析自动注入标识resolvedAutowireMode,默认值为AutowireCapableBeanFactory.AUTOWIRE_NO也就是0。当其为0时,不会执行autowireByName或者autowireByType逻辑。


postProcessProperties则可以理解为一种补偿机制,比如AutowiredAnnotationBeanPostProcessor的该方法,会尝试解析@Autowired注解触发依赖Bean的获取过程。


接下来我们从源码角度分析这两部分的流程。

【1】autowireByName和autowireByType

① autowireByName


当resolvedAutowireMode为1时,即AUTOWIRE_BY_NAME将会触发autowireByName(beanName, mbd, bw, newPvs);

方法源码如下:

//AbstractAutowireCapableBeanFactory#autowireByName
protected void autowireByName(
    String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 获取未满足的非简单类型的属性名称
  String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
  for (String propertyName : propertyNames) {
  // 如果当前容器包含该属性名称对应的bean
    if (containsBean(propertyName)) {
    // 触发Bean的获取
      Object bean = getBean(propertyName);
      //更新pvs
      pvs.add(propertyName, bean);
      // 注册记录beanName与依赖 bean名称
      registerDependentBean(propertyName, beanName);
      if (logger.isTraceEnabled()) {
        logger.trace("Added autowiring by name from bean name '" + beanName +
            "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
      }
    }
    else {
      if (logger.isTraceEnabled()) {
        logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
            "' by name: no matching bean found");
      }
    }
  }
}

方法如上所示,获取需要解析的依赖bean。遍历循环尝试从容器中获取bean,然后更新到pvs中。最后调用registerDependentBean方法进行beanName与依赖bean名称留存记录。

② registerDependentBean



registerDependentBean方法如下所示,其使用dependentBeanMapdependenciesForBeanMap记录了beanName都被依赖了哪些bean和dependentBeanName都依赖了哪些bean。

public void registerDependentBean(String beanName, String dependentBeanName) {
  String canonicalName = canonicalName(beanName);
  synchronized (this.dependentBeanMap) {
    Set<String> dependentBeans =
        this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
    if (!dependentBeans.add(dependentBeanName)) {
      return;
    }
  }
  synchronized (this.dependenciesForBeanMap) {
    Set<String> dependenciesForBean =
        this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
    dependenciesForBean.add(canonicalName);
  }
}


在DefaultSingletonBeanRegistry中维护了一系列final map。其中dependentBeanMap 表示 beanName---哪些bean依赖了beanName,dependenciesForBeanMap 表示 beanName---beanName依赖了哪些bean。


/** Map between dependent bean names: bean name to Set of dependent bean names. */
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
/** Map between depending bean names: bean name to Set of bean names for the bean's dependencies. */
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

③ autowireByType

// AbstractAutowireCapableBeanFactory#autowireByType
protected void autowireByType(
    String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
  TypeConverter converter = getCustomTypeConverter();
  if (converter == null) {
    converter = bw;
  }
  Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
  // 获取未满足的非简单类型的bean名称/属性名称,
  //如创建我们的XXXMapper时会解析sqlSessionFactory、sqlSessionTemplate
  String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
  // 遍历循环解析
  for (String propertyName : propertyNames) {
    try {
      // 获取属性描述符
      PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
      // Don't try autowiring by type for type Object: never makes sense,
      // even if it technically is a unsatisfied, non-simple property.
      // 如果属性类型是Object,直接抛出异常
      if (Object.class != pd.getPropertyType()) {
        // 获取写方法参数对象,就是setXXXXX方法的参数对象
        MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
        // Do not allow eager init for type matching in case of a prioritized post-processor.
        // 判断是否为PriorityOrdered对象,即可以忽略order排序规则
        // 如果是PriorityOrdered则eager为false,否则为true。
        boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
        DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
      // 核心方法,解析依赖
        Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
    // 如果解析到依赖对象,比如sqlSessionFactory,那么放到pvs中
        if (autowiredArgument != null) {
          pvs.add(propertyName, autowiredArgument);
        }
        for (String autowiredBeanName : autowiredBeanNames) {
        //该方法前面提到过,注册记录bean与依赖bean的关系
          registerDependentBean(autowiredBeanName, beanName);
          if (logger.isTraceEnabled()) {
            logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
                propertyName + "' to bean named '" + autowiredBeanName + "'");
          }
        }
        autowiredBeanNames.clear();
      }
    }
    catch (BeansException ex) {
      throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
    }
  }
}


PropertyDescriptor 属性描述符。其包括属性名称、读方法、写方法、属性类型等。


MethodParameter,方法参数类型。其包括方法调用类、所属类、参数类型、参数个数、方法名称、方法返回类型、参数注解、异常类型等等。


如上代码所示,这里会解析得到propertyNames然后遍历解析依赖,之后会同autowireByName一样调用registerDependentBean方法注册记录bean与依赖bean的关系。


那么如何解析依赖呢?我们继续往下看。

④ 依赖解析resolveDependency

继续分析autowireByType,这部分我们分析依赖如何解析的。如下是DefaultListableBeanFactory的resolveDependency方法,这也是依赖解析的核心方法。在下文AutowiredAnnotationBeanPostProcessor的inject同样流转到了该方法。

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
    @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 默认是DefaultParameterNameDiscoverer,在分析springmvc流程中我们也提到过
  descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 判断依赖类型,通常这里是parameterType
  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 {
  // 这里是核心入口,这里是ContextAnnotationAutowireCandidateResolver
  // 判断是否为Lazy,如果是则使用ProxyFactory创建代理
    Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
        descriptor, requestingBeanName);
    if (result == null) {
    // 如果非Lazy,则进入实际依赖解析过程
      result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
    }
    return result;
  }
}

如上代码所示,首先设置ParameterNameDiscoverer,默认是DefaultParameterNameDiscoverer。然后判断依赖类型,根据依赖类型进行不同的处理。其中在最后一部分中会判断是否为Lazy,如果是Lazy则使用ProxyFactory创建代理返回。如果不是Lazy则进入实际依赖解析过程。


Lazy时,创建代理的过程可以参考方法ContextAnnotationAutowireCandidateResolver的buildLazyResolutionProxy方法。关于AutowireCandidateResolver

如下所示,DefaultListableBeanFactory内部维护了该成员默认是SimpleAutowireCandidateResolver。

private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();


但是在AnnotationConfigUtils的registerAnnotationConfigProcessors方法中会为容器设置解析器为ContextAnnotationAutowireCandidateResolver,这整个候选解析器是QualifierAnnotationAutowireCandidateResolver的子类。


我们继续看public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException 方法,这是实际解析依赖的入口。

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
    @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
  InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
  try {
    Object shortcut = descriptor.resolveShortcut(this);
    if (shortcut != null) {
      return shortcut;
    }
//获取依赖类型,比如interface org.apache.ibatis.session.SqlSessionFactory
    Class<?> type = descriptor.getDependencyType();
  // 这部分处理 @Value 注解
  // value如${com.jane.file.baseFilePath}
    Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
    if (value != null) {
      if (value instanceof String) {
        String strVal = resolveEmbeddedValue((String) value);
        BeanDefinition bd = (beanName != null && containsBean(beanName) ?
            getMergedBeanDefinition(beanName) : null);
        value = evaluateBeanDefinitionString(strVal, bd);
      }
      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()));
      }
    }
// 处理集合类型,比如Array Map Collection
    Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
    if (multipleBeans != null) {
      return multipleBeans;
    }
// 得到候选的、匹配的bean class实例:beanName---bean class 对象
    Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
    if (matchingBeans.isEmpty()) {
    // 如果为空且required,则抛出异常NoSuchBeanDefinitionException
      if (isRequired(descriptor)) {
        raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
      }
      return null;
    }
    String autowiredBeanName;
    Object instanceCandidate;
    if (matchingBeans.size() > 1) {
    // 如果有多个,则根据@Primary和@Priority进行抉择
      autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
      if (autowiredBeanName == null) {
       //如果抉择不出,则可能抛出异常NoUniqueBeanDefinitionException
        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();
      // 解析得到的依赖bean名称
      autowiredBeanName = entry.getKey();
      // 解析得到的依赖bean实例-Class对象哦,还需要进一步解析
      instanceCandidate = entry.getValue();
    }
    if (autowiredBeanNames != null) {
    // 放入autowiredBeanNames,如sqlSessionFactory
      autowiredBeanNames.add(autowiredBeanName);
    }
    // 如果实例是Class对象,则解析为真实的Bean实例对象
    if (instanceCandidate instanceof Class) {
      // beanFactory.getBean(beanName); 也就是getBean的过程
      instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
    }
    Object result = instanceCandidate;
    if (result instanceof NullBean) {
      if (isRequired(descriptor)) {
      // 抛出NoSuchBeanDefinitionException
        raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
      }
      result = null;
    }
    if (!ClassUtils.isAssignableValue(type, result)) {
    // 抛出BeanNotOfRequiredTypeException
      throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
    }
    return result;
  }
  finally {
    ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
  }
}

如上代码所示,这里可以总结为三个核心方法:


resolveMultipleBeans,处理集合类型,如Array、Map、Collection;

findAutowireCandidates,处理单个对象

descriptor.resolveCandidate(autowiredBeanName, type, this);,将Class对象解析为真实的bean实例,这里会触发getBean的过程。可以说真正的依赖解析是在这里实行的。

————————————————

⑤ @Value

在上面方法中可以看到如下代码,其实就是对@Value注解做了处理。

Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);


如下所示,AbstractBeanFactoryresolveEmbeddedValue方法会尝试使用StringValueResolver解析得到实际的Value值,比如本文这里的D://myfilemapping/bookrecommend/file


【2】postProcessProperties


这里指的是InstantiationAwareBeanPostProcessor的postProcessProperties。前面我们提到过,如果resolvedAutowireMode为0,那么是不会执行autowireByName或者autowireByType的逻辑的。此时@Autowired、@Resource注解就由postProcessProperties方法提供实习。


AutowiredAnnotationBeanPostProcessor处理@Autowired,CommonAnnotationBeanPostProcessor处理@Resource。

如下所示是AutowiredAnnotationBeanPostProcessor的postProcessProperties方法,该方法首先获取到需要依赖注入的元素,然后调用注入方法得到实例对象。

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 获取需要依赖注入的元素
  InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
  try {
  // 启动注入过程
    metadata.inject(bean, beanName, pvs);
  }
  catch (BeanCreationException ex) {
    throw ex;
  }
  catch (Throwable ex) {
    throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
  }
  return pvs;
}

① 获取依赖注入的元素

如下所示AutowiredAnnotationBeanPostProcessorfindAutowiringMetadata方法找到那些标注了@Autowired注解的字段和方法,提取出来需要进行依赖解析的元素。

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
  // Fall back to class name as cache key, for backwards compatibility with custom callers.
  String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
  // Quick check on the concurrent map first, with minimal locking.
  InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
  if (InjectionMetadata.needsRefresh(metadata, clazz)) {
    synchronized (this.injectionMetadataCache) {
      metadata = this.injectionMetadataCache.get(cacheKey);
      if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        if (metadata != null) {
          metadata.clear(pvs);
        }
        metadata = buildAutowiringMetadata(clazz);
        this.injectionMetadataCache.put(cacheKey, metadata);
      }
    }
  }
  return metadata;
}
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
  if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
    return InjectionMetadata.EMPTY;
  }
  List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
  Class<?> targetClass = clazz;
  do {
    final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
    ReflectionUtils.doWithLocalFields(targetClass, field -> {
      MergedAnnotation<?> ann = findAutowiredAnnotation(field);
      if (ann != null) {
        if (Modifier.isStatic(field.getModifiers())) {
          if (logger.isInfoEnabled()) {
            logger.info("Autowired annotation is not supported on static fields: " + field);
          }
          return;
        }
        boolean required = determineRequiredStatus(ann);
        currElements.add(new AutowiredFieldElement(field, required));
      }
    });
    ReflectionUtils.doWithLocalMethods(targetClass, method -> {
      Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
      if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
        return;
      }
      MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
      if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
        if (Modifier.isStatic(method.getModifiers())) {
          if (logger.isInfoEnabled()) {
            logger.info("Autowired annotation is not supported on static methods: " + method);
          }
          return;
        }
        if (method.getParameterCount() == 0) {
          if (logger.isInfoEnabled()) {
            logger.info("Autowired annotation should only be used on methods with parameters: " +
                method);
          }
        }
        boolean required = determineRequiredStatus(ann);
        PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
        currElements.add(new AutowiredMethodElement(method, required, pd));
      }
    });
    elements.addAll(0, currElements);
    targetClass = targetClass.getSuperclass();
  }
  while (targetClass != null && targetClass != Object.class);
  return InjectionMetadata.forElements(elements, clazz);
}


② 依赖注入对象解析

接下来我们再看一下注入过程

// InjectionMetadata#inject
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
  Collection<InjectedElement> checkedElements = this.checkedElements;
  Collection<InjectedElement> elementsToIterate =
      (checkedElements != null ? checkedElements : this.injectedElements);
  if (!elementsToIterate.isEmpty()) {
  // 遍历每一个元素,触发注入过程
    for (InjectedElement element : elementsToIterate) {
      if (logger.isTraceEnabled()) {
        logger.trace("Processing injected element of bean '" + beanName + "': " + element);
      }
      element.inject(target, beanName, pvs);
    }
  }
}
// AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
@Override
  protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    Field field = (Field) this.member;
    Object value;
    // 这是缓存机制
    if (this.cached) {
      value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    }
    else {
      DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
      desc.setContainingClass(bean.getClass());
      Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
      Assert.state(beanFactory != null, "No BeanFactory available");
      TypeConverter typeConverter = beanFactory.getTypeConverter();
      try {
      // 这里是核心,解析依赖
        value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
      }
      catch (BeansException ex) {
        throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
      }
      synchronized (this) {
        if (!this.cached) {
          if (value != null || this.required) {
            this.cachedFieldValue = desc;
            // 记录bean与依赖bean的关系
            registerDependentBeans(beanName, autowiredBeanNames);
            if (autowiredBeanNames.size() == 1) {
              String autowiredBeanName = autowiredBeanNames.iterator().next();
              if (beanFactory.containsBean(autowiredBeanName) &&
                  beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                this.cachedFieldValue = new ShortcutDependencyDescriptor(
                    desc, autowiredBeanName, field.getType());
              }
            }
          }
          else {
            this.cachedFieldValue = null;
          }
          this.cached = true;
        }
      }
    }
    // 如果value不为null,则为filed赋值value
    if (value != null) {
      ReflectionUtils.makeAccessible(field);
      field.set(bean, value);
    }
  }
}


如上代码所示,这里核心逻辑就是 beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);其将会触发依赖解析过程也就是【1】中的第③部分。


③ @Resource

当你controller有@Resource注解时,CommonAnnotationBeanPostProcessor的postProcessProperties方法就会去解析并注入。

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
  InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
  try {
    metadata.inject(bean, beanName, pvs);
  }
  catch (Throwable ex) {
    throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
  }
  return pvs;
}
private InjectionMetadata findResourceMetadata(String beanName, final Class<?> clazz, @Nullable PropertyValues pvs) {
  // Fall back to class name as cache key, for backwards compatibility with custom callers.
  String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
  // Quick check on the concurrent map first, with minimal locking.
  // 首先从缓存里面查找
  InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
  // metadata == null || metadata.targetClass != clazz
  if (InjectionMetadata.needsRefresh(metadata, clazz)) {
  // 加锁--双重校验锁
    synchronized (this.injectionMetadataCache) {
    //再次从缓存获取
      metadata = this.injectionMetadataCache.get(cacheKey);
      // 再次进行判断
      if (InjectionMetadata.needsRefresh(metadata, clazz)) {
        if (metadata != null) {
          metadata.clear(pvs);
        }
        // 核心在这里,根据Bean类型获取其需要处理的@Resource元素
        metadata = buildResourceMetadata(clazz);
        // 放入缓存
        this.injectionMetadataCache.put(cacheKey, metadata);
      }
    }
  }
  return metadata;
}


我们看下其收集元素的方法,这里将会收集目标元素如WebServiceRefElement(@WebServiceRef)EjbRefElement(@EJB)及我们常用的ResourceElement(@Resource)

private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
  if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
    return InjectionMetadata.EMPTY;
  }
  List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
  Class<?> targetClass = clazz;
  do {
    final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
// 从field字段级别收集
    ReflectionUtils.doWithLocalFields(targetClass, field -> {
      if (webServiceRefClass != null && field.isAnnotationPresent(webServiceRefClass)) {
        if (Modifier.isStatic(field.getModifiers())) {
          throw new IllegalStateException("@WebServiceRef annotation is not supported on static fields");
        }
        currElements.add(new WebServiceRefElement(field, field, null));
      }
      else if (ejbRefClass != null && field.isAnnotationPresent(ejbRefClass)) {
        if (Modifier.isStatic(field.getModifiers())) {
          throw new IllegalStateException("@EJB annotation is not supported on static fields");
        }
        currElements.add(new EjbRefElement(field, field, null));
      }
      else if (field.isAnnotationPresent(Resource.class)) {
        if (Modifier.isStatic(field.getModifiers())) {
          throw new IllegalStateException("@Resource annotation is not supported on static fields");
        }
        if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
          currElements.add(new ResourceElement(field, field, null));
        }
      }
    });
// 从方法级别收集
    ReflectionUtils.doWithLocalMethods(targetClass, method -> {
      Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
      if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
        return;
      }
      if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
        if (webServiceRefClass != null && bridgedMethod.isAnnotationPresent(webServiceRefClass)) {
          if (Modifier.isStatic(method.getModifiers())) {
            throw new IllegalStateException("@WebServiceRef annotation is not supported on static methods");
          }
          if (method.getParameterCount() != 1) {
            throw new IllegalStateException("@WebServiceRef annotation requires a single-arg method: " + method);
          }
          PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
          currElements.add(new WebServiceRefElement(method, bridgedMethod, pd));
        }
        else if (ejbRefClass != null && bridgedMethod.isAnnotationPresent(ejbRefClass)) {
          if (Modifier.isStatic(method.getModifiers())) {
            throw new IllegalStateException("@EJB annotation is not supported on static methods");
          }
          if (method.getParameterCount() != 1) {
            throw new IllegalStateException("@EJB annotation requires a single-arg method: " + method);
          }
          PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
          currElements.add(new EjbRefElement(method, bridgedMethod, pd));
        }
        else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
          if (Modifier.isStatic(method.getModifiers())) {
            throw new IllegalStateException("@Resource annotation is not supported on static methods");
          }
          Class<?>[] paramTypes = method.getParameterTypes();
          if (paramTypes.length != 1) {
            throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
          }
          if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
            PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
            currElements.add(new ResourceElement(method, bridgedMethod, pd));
          }
        }
      }
    });
    elements.addAll(0, currElements);
    targetClass = targetClass.getSuperclass();
  }
  while (targetClass != null && targetClass != Object.class);
  return InjectionMetadata.forElements(elements, clazz);
}


9ca918dab6bf4c03a09004f395781fbb.png


获取到目标元素后(比如我们@Resource注解的对象),其将会通过如下方法调用栈进行依赖的解析。

// 方法调用栈
InjectionMetadata#inject ->
InjectionMetadata.InjectedElement#inject ->
CommonAnnotationBeanPostProcessor.ResourceElement#getResourceToInject ->
CommonAnnotationBeanPostProcessor#getResource ->
CommonAnnotationBeanPostProcessor#autowireResource ->
DefaultListableBeanFactory#resolveDependency


这里我们最后可以看到,其同样走到了DefaultListableBeanFactoryd的resolveDependency方法,不再赘述。


需要注意一点的是,同@Autowired解析依赖的过程一样,这里也实现了lazyLookup 兼容。如果lazyLookup 为true,则创建代理,不触发实际对象解析。

// CommonAnnotationBeanPostProcessor.ResourceElement#getResourceToInject
@Override
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
  return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
      getResource(this, requestingBeanName));
}


目录
相关文章
|
2月前
|
XML Java 程序员
Spring6框架中依赖注入的多种方式(推荐构造器注入)
依赖注入(DI)是一种过程,对象通过构造函数参数、工厂方法的参数或在对象实例构建后设置的属性来定义它们的依赖关系(即与其一起工作的其他对象)。
41 3
|
6天前
|
监控 Java 数据安全/隐私保护
Spring AOP实现原理及其在企业应用中的实际应用
Spring AOP实现原理及其在企业应用中的实际应用
|
10天前
|
Java Spring 容器
spring如何进行依赖注入,通过set方法把Dao注入到serves
spring如何进行依赖注入,通过set方法把Dao注入到serves
|
25天前
|
Java Spring
解决 Spring 中 Prototype Bean 注入后被固定的问题
【6月更文挑战第8天】学习 Spring 框架内不原理的意义就是,当遇到问题时,分析出原因,就可以从多个切入点,利用 Spring 的特性,来解决问题。
33 2
|
6天前
|
监控 Java 数据安全/隐私保护
Spring AOP实现原理及其在企业应用中的实际应用
Spring AOP实现原理及其在企业应用中的实际应用
|
1月前
spring-boot报错循环注入报错:has been injected into other beans
spring-boot报错循环注入报错:has been injected into other beans
74 3
|
10天前
|
Java Linux 程序员
技术笔记:Spring生态研习【五】:Springboot中bean的条件注入
技术笔记:Spring生态研习【五】:Springboot中bean的条件注入
|
22天前
|
SQL 安全 Java
Spring Boot中的跨站点脚本攻击(XSS)与SQL注入防护
【6月更文挑战第15天】在现代Web应用程序开发中,安全性是一个至关重要的课题。跨站点脚本攻击(XSS)和SQL注入是最常见的两种攻击类型,它们可以严重威胁到应用程序的安全。
96 0
|
2月前
|
前端开发 Java 编译器
详解Spring与JDK注入
依赖注入是Spring框架的核心概念之一,它通过将对象之间的依赖关系外部化,实现了松耦合和可测试性。面向切面编程则允许开发人员将横切关注点(如日志、事务管理)从应用程序的主要业务逻辑中分离出来,以提高代码的模块化和可维护性。
27 4
|
2月前
|
设计模式 Java 测试技术
Spring状态机的实现原理和业务场景
**Spring State Machine**是Spring框架的一部分,它提供了一种实现状态机的方式,允许开发者定义状态机的状态、事件、行为和转换。状态机是一种计算模型,根据一系列规则从一个状态转移到另一个状态。【5月更文挑战第4天】