您的位置 首页 golang

深入理解Spring一(11)Bean的依赖注入IOC

populateBean方法处理Bean的依赖注入。最终是由InstantiationAwareBeanPostProcessor实现的,核心实现类有AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor。

 for (BeanPostProcessor bp : getBeanPostProcessors()) {
   if (bp instanceof InstantiationAwareBeanPostProcessor) {
      InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
      PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
    //省略代码
   }
}  

一、AutowiredAnnotationBeanPostProcessor

处理三种注解Autowired、Value、Inject

 public AutowiredAnnotationBeanPostProcessor() {
   this.autowiredAnnotationTypes.add(Autowired.class);
   this.autowiredAnnotationTypes.add(Value.class);
   try {
      this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
            ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
      logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
   }
   catch (ClassNotFoundException ex) {
      // JSR-330 API not available - simply skip.
   }
}  

实现依赖注入的方法

 @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;
}  

最终基于注入的方式,会分别创建AutowiredFieldElement和AutowiredMethodElement,工作中经常使用的是AutowiredFieldElement基于Field的注入。

我们看一下AutowiredFieldElement的注入实现方法

 @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);
      }
      //省略代码
   }
   if (value != null) {
      ReflectionUtils.makeAccessible(field);
      field.set(bean, value);
   }
}  

最终查找依赖的bean的方法是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 {
      //省略代码
      Class<?> type = descriptor.getDependencyType();
      //处理@Value注解
      //这个value值就是我们经常使用的占位符${a.b.c}
      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());
         }
      }
//省略代码
     //我们经常使用的普通对象的解析
      if (instanceCandidate instanceof Class) {
         instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
      }
      Object result = instanceCandidate;
    
      return result;
   }
   finally {
      ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
   }
}  

${}占位符的解析,最终是由PlaceholderResolvingStringValueResolver来实现的。

 @Override
@Nullable
public String resolveEmbeddedValue(@Nullable String value) {
   if (value == null) {
      return null;
   }
   String result = value;
   for (StringValueResolver resolver : this.embeddedValueResolvers) {
      result = resolver.resolveStringValue(result);
      if (result == null) {
         return null;
      }
   }
   return result;
}  
 private class PlaceholderResolvingStringValueResolver implements StringValueResolver {

   private final PropertyPlaceholderHelper helper;

   private final PlaceholderResolver resolver;

   public PlaceholderResolvingStringValueResolver(Properties props) {
      this.helper = new PropertyPlaceholderHelper(
            placeholderPrefix, placeholderSuffix, valueSeparator, ignoreUnresolvablePlaceholders);
      this.resolver = new PropertyPlaceholderConfigurerResolver(props);
   }

   @Override
   @Nullable
   public String resolveStringValue(String strVal) throws BeansException {
      String resolved = this.helper.replacePlaceholders(strVal, this.resolver);
      if (trimValues) {
         resolved = resolved.trim();
      }
      return (resolved.equals(nullValue) ? null : resolved);
   }
}  

普通对象的解析比较简单,也是最经常使用的。

 public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
      throws BeansException {

   return beanFactory.getBean(beanName);
}  

二、CommonAnnotationBeanPostProcessor

处理Resource注解,创建的是ResourceElement对象

 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));
   }
}  

ResourceElement实现了获取Bean的方法,最终获取Resource注解Bean的入口如下

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

三、总结

Spring的IOC是通过InstantiationAwareBeanPostProcessor来实现的,主要有两个实现类AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor。AutowiredAnnotationBeanPostProcessor实现Autowired、Value、Inject的注入,CommonAnnotationBeanPostProcessor实现Resource的注入。

文章来源:智云一二三科技

文章标题:深入理解Spring一(11)Bean的依赖注入IOC

文章地址:https://www.zhihuclub.com/88720.shtml

关于作者: 智云科技

热门文章

网站地图