@Resource аннотация исходного кода Spring

Spring исходный код
@Resource аннотация исходного кода Spring

1. Краткое введение в аннотацию @Resource

Свойства, отмеченные аннотацией @Resource, по умолчанию вводятся в соответствии с ByName, который предоставляется J2EE.

Если мы хотим инъектировать по ByType, то код должен быть написан так:

public class LaController {
    //按类型注入
    @Resource(type=LaService.class)
    private LaService  laService;
}

Если в интерфейсе LaService есть два класса реализации, и оба класса реализации будут сканироваться Spring, во время инъекции будет сообщено об ошибке: вложенное исключение
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.netty.use.nettyuse.service.LaService' available: expected single matching bean but found 2: la2ServiceImpl,laServiceImpl

type также может быть классом реализации, например:

public class LaController {
    //按类型注入
    @Resource(type=La2ServiceImpl.class)
    private LaService  laService;
}

Таким образом, будет внедрен экземпляр La2ServiceImpl, и указанная выше ошибка не появится.

2. Подробное объяснение исходного кода инъекции

код для
Метод populateBean класса AbstractAutowireCapableBeanFactory

//是否有实例化相关的BeanPostProcessor
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

if (hasInstAwareBpps || needsDepCheck) {
   if (pvs == null) {
      pvs = mbd.getPropertyValues();
   }
   PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
   if (hasInstAwareBpps) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
         if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            //调用处理属性值的方法
            pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvs == null) {
               return;
            }
         }
      }
   }
   if (needsDepCheck) {
      checkDependencies(beanName, mbd, filteredPds, pvs);
   }
}


InstantiationAwareBeanPostProcessor имеет класс реализации под названием CommonAnnotationBeanPostProcessor, который присваивает значения свойствам, помеченным @Resource.

1. Найдите все аннотированные свойства @Resource

Используйте отражение Java, чтобы найти все поля в классе, а затем определить, отмечена ли аннотация @Resource в атрибуте

if(field.isAnnotationPresent(Resource.class))

Если условие истинно, ResourceElement будет создан. Давайте посмотрим на класс ResourceElement

private class ResourceElement extends LookupElement {

   private final boolean lazyLookup;
   //构造函数
   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();
      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());
   }

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

Наконец, все ResourceElements, созданные из атрибутов, аннотированных аннотациями @Resource в этом классе, будут помещены в LinkedList. Наконец, объект метаданных внедрения (InjectionMetadata) будет упакован.

2. Внедрение значения атрибута @Resource

Теперь, когда у нас есть все свойства @Resource, мы можем перебрать эти свойства и внедрить их.

Основной принцип внедрения свойств = отражение + метод getBean.

Метод getBean получает объект Bean, а затем вызывает метод set Field для присвоения значений свойствам. Давайте посмотрим на фрагмент кода:

if (this.isField) {
   Field field = (Field) this.member;
   ReflectionUtils.makeAccessible(field);
   field.set(target, getResourceToInject(target, requestingBeanName));
}