@Resource注解注入源码解析

doMore 372 2023-10-25

源码解析

javax.annotation.Resource 归属 Java 源码包,主流的服务容器都支持使用它进行依赖注入。

再次进行 spring 源码解析,进一步加深理解。

  1. @Resource 解析入口 org.springframework.context.annotation.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;  
}

  1. 查询注入点 org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#findResourceMetadata
private InjectionMetadata findResourceMetadata(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);  
    // 判断是否为空 或者 是否是 Class 对象  
    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 = buildResourceMetadata(clazz);  
                // 加入缓存  
                this.injectionMetadataCache.put(cacheKey, metadata);  
            }  
        }  
    }  
    return metadata;  
}

  1. 真正查询并构建注入点方法 org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#buildResourceMetadata

private InjectionMetadata buildResourceMetadata(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<>();  
		// 属性 依据不同的注解 解析 并构建 InjectedElement 对象
       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 (ejbClass != null && field.isAnnotationPresent(ejbClass)) {  
             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));  
             }  
          }  
       });  

		// 方法 依据不同的注解 解析 并构建 InjectedElement 对象
       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 (ejbClass != null && bridgedMethod.isAnnotationPresent(ejbClass)) {  
                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);  
}


此处只关注 对于 @Resource 注解的解析。

  1. 构建 ResourceElement

public ResourceElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) {  
    super(member, pd);  
    Resource resource = ae.getAnnotation(Resource.class);  
    String resourceName = resource.name();  
    Class<?> resourceType = resource.type();  
    // 查看 Resource 注解中是否指定了 name 
    this.isDefaultName = !StringUtils.hasLength(resourceName);  
    if (this.isDefaultName) {  
       resourceName = this.member.getName();  
       // 判断 是否是 标注在 方法上
       if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) {  
          resourceName = Introspector.decapitalize(resourceName.substring(3));  
       }  
    }  
    else if (embeddedValueResolver != null) {  
       resourceName = embeddedValueResolver.resolveStringValue(resourceName);  
    }  
    if (Object.class != resourceType) {  
       checkResourceType(resourceType);  
    }  
    else {  
       // No resource type specified... check field/method.  
       resourceType = getResourceType();  
    }  
    this.name = (resourceName != null ? resourceName : "");  
    this.lookupType = resourceType;  
    String lookupValue = resource.lookup();  
    this.mappedName = (StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName());  
    Lazy lazy = ae.getAnnotation(Lazy.class);  
    this.lazyLookup = (lazy != null && lazy.value());  
}

  1. 构建完成 注入的元素之后,再看 执行注入的方法 org.springframework.beans.factory.annotation.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) {  
       // 调用上一步 构建的元素的 注入方法
          element.inject(target, beanName, pvs);  
       }  
    }  
}


protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)  
       throws Throwable {  
	// 判断是否是属性,如果是,则反射赋值
    if (this.isField) {  
       Field field = (Field) this.member;  
       ReflectionUtils.makeAccessible(field);  
       field.set(target, getResourceToInject(target, requestingBeanName));  
    }  
    else {  
    // 检查是否需要跳过该属性,并且 标记已经处理
       if (checkPropertySkipping(pvs)) {  
          return;  
       }  
       try {  
          // 执行方法进行赋值
          Method method = (Method) this.member;  
          ReflectionUtils.makeAccessible(method);  
          method.invoke(target, getResourceToInject(target, requestingBeanName));  
       }  
       catch (InvocationTargetException ex) {  
          throw ex.getTargetException();  
       }  
    }  
}

  1. 重点关注 org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.ResourceElement#getResourceToInject

此处不进行懒加载分析


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

// org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#getResource
protected Object getResource(LookupElement element, @Nullable String requestingBeanName)  
       throws NoSuchBeanDefinitionException {  
  
    // JNDI lookup to perform?  
    String jndiName = null;  
    if (StringUtils.hasLength(element.mappedName)) {  
       jndiName = element.mappedName;  
    }  
    else if (this.alwaysUseJndiLookup) {  
       jndiName = element.name;  
    }  
    if (jndiName != null) {  
       if (this.jndiFactory == null) {  
          throw new NoSuchBeanDefinitionException(element.lookupType,  
                "No JNDI factory configured - specify the 'jndiFactory' property");  
       }  
       return this.jndiFactory.getBean(jndiName, element.lookupType);  
    }  
  
    // Regular resource autowiring  
    if (this.resourceFactory == null) {  
       throw new NoSuchBeanDefinitionException(element.lookupType,  
             "No resource factory configured - specify the 'resourceFactory' property");  
    }  
    // 最后会走到这里
    // this.resourceFactory 默认情况下为  org.springframework.beans.factory.support.DefaultListableBeanFactory
    return autowireResource(this.resourceFactory, element, requestingBeanName);  
}



// org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#autowireResource
protected Object autowireResource(BeanFactory factory, LookupElement element, @Nullable String requestingBeanName)  
       throws NoSuchBeanDefinitionException {  
  
    Object resource;  
    Set<String> autowiredBeanNames;  
    String name = element.name;  
  
    if (factory instanceof AutowireCapableBeanFactory) {  
       AutowireCapableBeanFactory beanFactory = (AutowireCapableBeanFactory) factory;  
       DependencyDescriptor descriptor = element.getDependencyDescriptor();  
       // 判断 是否通过类型匹配,名称匹配,是否已经创建
       if (this.fallbackToDefaultTypeMatch && element.isDefaultName && !factory.containsBean(name)) {  
          // 该类型的所有名称
          autowiredBeanNames = new LinkedHashSet<>();
        // 解析获取 符合注入条件的对象  
        // 注解中无特殊指定,会走到这里
          resource = beanFactory.resolveDependency(descriptor, requestingBeanName, autowiredBeanNames, null);  
          if (resource == null) {  
             throw new NoSuchBeanDefinitionException(element.getLookupType(), "No resolvable resource object");  
          }  
       }  
       else {  
       // 如果在 @Resource 注解中指定了 name,则只会根据 名称注入
          resource = beanFactory.resolveBeanByName(name, descriptor);  
          autowiredBeanNames = Collections.singleton(name);  
       }  
    }  
    else {  
       resource = factory.getBean(name, element.lookupType);  
       autowiredBeanNames = Collections.singleton(name);  
    }  
  
    if (factory instanceof ConfigurableBeanFactory) {  
       ConfigurableBeanFactory beanFactory = (ConfigurableBeanFactory) factory;  
       for (String autowiredBeanName : autowiredBeanNames) {  
          if (requestingBeanName != null && beanFactory.containsBean(autowiredBeanName)) {  
             beanFactory.registerDependentBean(autowiredBeanName, requestingBeanName);  
          }  
       }  
    }  
  
    return resource;  
}


  1. 获取符合注入条件的对象 org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,  
       @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {  
  
    descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());  
    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;  
    }  
}




// org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
@Nullable  
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;  
       }  
  
       Class<?> type = descriptor.getDependencyType();  
       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()));  
          }  
       }  
  
       Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);  
       if (multipleBeans != null) {  
          return multipleBeans;  
       }  
		
		// 根据 类型和 名称查找符合条件的对象
       Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);  
       if (matchingBeans.isEmpty()) {  
          if (isRequired(descriptor)) {  
             raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);  
          }  
          return null;  
       }  
  
       String autowiredBeanName;  
       Object instanceCandidate;  
		// 查找到多个符合条件的 进行下一步判断  如 @Primary 和 优先级 @Order 等注解
       if (matchingBeans.size() > 1) {  
          autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);  
          if (autowiredBeanName == null) {  
             if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {  
                return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);  
             }  
             // 无法确定明确对象的返回 null
             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);  
       }  
       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);  
    }  
}


  1. 查找符合条件的对象 org.springframework.beans.factory.support.DefaultListableBeanFactory#findAutowireCandidates

protected Map<String, Object> findAutowireCandidates(  
       @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {  
  // 获取该类型 所有的名称
    String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(  
          this, requiredType, true, descriptor.isEager());  
    Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);  
    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;  
          }  
       }  
    }  
    // 判断是否是自引用 是否符合 
    // isAutowireCandidate  ->  Determine whether the specified bean definition qualifies as an autowire candidate, to be injected into other beans which declare a dependency of matching type.   确定指定的bean定义是否有资格作为自动候选对象,以注入声明匹配类型依赖的其他bean中。
    for (String candidate : candidateNames) {  
       if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {  
          addCandidateEntry(result, candidate, descriptor, requiredType);  
       }  
    }  
    // 第一轮没有找到符合的对象,在进行额外的处理
    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) {  
          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;  
}


总结

  1. @Resource 注解中指定了 name ,只会根据名称注入,找不到就会报错。
  2. @Resource 注解中没有指定 name,则会根据类型、名称 去找符合条件的对象进行注入。