Spring源码解析系列三:Spring的IOC容器的属性注入源码详解

Spring的IOC容器的属性注入

本文只分析属性的注入,根据源码分析AbstractAutowireCapableBeanFactory的populateBean方法

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
   
   if (bw == null) {
   
      if (mbd.hasPropertyValues()) {
   
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
      }
      else {
   
         // Skip property population phase for null instance.
         return;
      }
   }

   // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
   // state of the bean before properties are set. This can be used, for example,
   // to support styles of field injection.
   boolean continueWithPropertyPopulation = true;

   // 到这步的时候,bean 实例化完成(通过工厂方法或构造方法),但是还没开始属性设值,
   // InstantiationAwareBeanPostProcessor 的实现类可以在这里对 bean 进行状态修改,
   if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
   
      // 如果mbd不是合成的 && 存在InstantiationAwareBeanPostProcessor,则遍历处理InstantiationAwareBeanPostProcessor
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
   
         if (bp instanceof InstantiationAwareBeanPostProcessor) {
   
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            // 如果返回 false,代表不需要进行后续的属性设值,也不需要再经过其他的 BeanPostProcessor 的处理
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
   
               continueWithPropertyPopulation = false;
               break;
            }
         }
      }
   }

   // 如果continueWithPropertyPopulation为false,则跳过之后的属性填充
   if (!continueWithPropertyPopulation) {
   
      return;
   }

   PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

   // 解析自动装配模式为AUTOWIRE_BY_NAME和AUTOWIRE_BY_TYPE(用于注入)
   if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
   
      MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
      // Add property values based on autowire by name if applicable.
      // 通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系
      if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
   
         // 解析autowireByName的注入
         autowireByName(beanName, mbd, bw, newPvs);
      }
      // Add property values based on autowire by type if applicable.
      // 通过类型装配。复杂一些
      if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
   
         // 解析autowireByType的注入
         autowireByType(beanName, mbd, bw, newPvs);
      }
      pvs = newPvs;
   }

   // BeanFactory是否注册过InstantiationAwareBeanPostProcessors
   boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
   // 是否需要依赖检查
   boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

   // 注册过InstantiationAwareBeanPostProcessors 或者 需要依赖检查
   if (hasInstAwareBpps || needsDepCheck) {
   
      if (pvs == null) {
   
         pvs = mbd.getPropertyValues();
      }
      //获取出对象的所有set get方法
      PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      if (hasInstAwareBpps) {
   
         // 应用后置处理器InstantiationAwareBeanPostProcessor
         for (BeanPostProcessor bp : getBeanPostProcessors()) {
   
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
   
               InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
               // 这里有个非常有用的 BeanPostProcessor
               // 进到这里: AutowiredAnnotationBeanPostProcessor
               // 对采用 @Autowired、@Value、@Resource 注解的依赖进行设值,
               if(logger.isInfoEnabled()){
   
                  logger.info("调用InstantiationAwareBeanPostProcessor的实例:"+bp.getClass().getSimpleName()+"的postProcessPropertyValues方法," +
                        "\n说明:AutowiredAnnotationBeanPostProcessor对采用 @Autowired、@Value 注解的依赖进行设值");
               }
               pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
               if (pvs == null) {
   
                  return;
               }
            }
         }
      }
      if (needsDepCheck) {
   
         // 依赖检查,对应depends-on属性
         checkDependencies(beanName, mbd, filteredPds, pvs);
      }
   }

   if (pvs != null) {
   
      // 将所有PropertyValues中的属性填充到bean中
      applyPropertyValues(beanName, mbd, bw, pvs);
   }
}
  1. 解析自动装配模式为AUTOWIRE_BY_NAME和AUTOWIRE_BY_TYPE(需要放入三方的bean到Spring容器中时,这时候没办法使用注解)要注入的属性
  2. @Autowired、@Value、@Resource注解解析,反射注入属性
  3. 步骤1以及XML配置文件中属性注入

构造方法有参注入

详见Spring的IOC容器实例化Bean的方式源码详解

根据名称注入

最佳实践

使用注解:

@Bean(autowire = Autowire.BY_NAME)
public AutoWireTestService2 autoWireTestService2() {
   
   return new AutoWireTestService2();
}
public class AutoWireTestService2 {
   

   private HelloService helloService;

   public void setHelloService(HelloService helloService) {
   
      this.helloService = helloService;
   }
}

使用XML:

在这里插入图片描述

源码解析

protected void autowireByName(
      String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
   
   // 寻找bw中需要依赖注入的属性
   String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
   for (String propertyName : propertyNames) {
   
      // 校验是否存在beanName=propertyName的bean实例或者BeanDefinition
      if (containsBean(propertyName)) {
   
         // 获取propertyName的bean实例对象
         Object bean = getBean(propertyName);
         // 将属性名和属性值添加到pvs
         pvs.add(propertyName, bean);
         // 注册依赖关系到缓存(beanName依赖propertyName)
         registerDependentBean(propertyName, beanName);
         if (logger.isDebugEnabled()) {
   
            logger.debug("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");
         }
      }
   }
}
  1. 得到需要依赖注入的属性:获取实例化的Bean中,写入属性值的方法(set方法)不为空 && pd不是从依赖性检查中排除的bean属性 && pd不包含在pvs里&& pd的属性类型不是“简单”属性(基础类型、枚举、Number等)的属性。
  2. 其中要注入的属性名称是:例如setXXX方法-setNam的名称是nam,根据nam从容器中获取Bean。
  3. 根据要注入的属性名称从Spring容器中获取要注入的Bean。
  4. 将要注入的属性加入到pvs中,之后再反射注入

分析要依赖注入的属性

protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
   
   Set<String> result = new TreeSet<>();
   // 拿到mdb的属性值
   PropertyValues pvs = mbd.getPropertyValues();
   // 拿到bw的PropertyDescriptors
   PropertyDescriptor[] pds = bw.getPropertyDescriptors();
   // 遍历bw的PropertyDescriptors
   for (PropertyDescriptor pd : pds) {
   
      // pd用于写入属性值的方法不为空 && pd不是从依赖性检查中排除的bean属性 && pd不包含在pvs里
      // && pd的属性类型不是“简单”属性(基础类型、枚举、Number等)
      // isSimpleProperty: 判断属性是不是“简单”属性
      if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
            !BeanUtils.isSimpleProperty(pd.getPropertyType())) {
   
         // 符合条件,则添加pd的name到result中,例如setNam的名称是nam
         result.add(pd.getName());
      }
   }
   return StringUtils.toStringArray(result);
}

其中PropertyDescriptor中存放的是类中的setXXX、getXXX以及isXXX方法(暂不分析)

小结

  • set方法的例如setNam的名称是nam,根据名称从Spring容器中获取要注入的属性,该属性需要有set方法且属性类型不是简单类型,如果容器中没有该属性的bean时,则不注入该属性。
  1. 得到需要依赖注入的属性:获取实例化的Bean中,写入属性值的方法(set方法)不为空 && pd不是从依赖性检查中排除的bean属性 && pd不包含在pvs里&& pd的属性类型不是“简单”属性(基础类型、枚举、Number等)的属性。
  2. 其中要注入的属性名称是:例如setXXX方法-setNam的名称是nam,根据nam从容器中获取Bean。
  3. 根据要注入的属性名称从Spring容器中获取要注入的Bean,如果容器中没有该属性的bean时,则不注入该属性。
  4. 将要注入的属性加入到pvs中,之后再反射注入

根据类型注入

最佳实践

@Bean(autowire = Autowire.BY_TYPE)
public static AutoWireTestService3 autoWireTestService3() {
   
   return new AutoWireTestService3();
}
public class AutoWireTestService3 {
   

   private HelloService helloService;

   public void setHelloService(HelloService helloService) {
   
      this.helloService = helloService;
   }
}

Mybatis与Spring整合的时候,在MapperFactoryBean实例类中注入SqlSessionFactory

在BeanDefinition中设置注入方式是根据类型注入

private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
   
  GenericBeanDefinition definition;
  for (BeanDefinitionHolder holder : beanDefinitions) {
   
    definition = (GenericBeanDefinition) holder.getBeanDefinition();
    String beanClassName = definition.getBeanClassName();
    LOGGER.debug(() -> "Creating MapperFactoryBean with name '" + holder.getBeanName()
        + "' and '" + beanClassName + "' mapperInterface");

    // the mapper interface is the original class of the bean
    // but, the actual class of the bean is MapperFactoryBean
    // 设置有参构造的入参是 要注入接口的全类名
    definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); // issue #59
    // 设置BeanClass为mapperFactoryBean
    definition.setBeanClass(this.mapperFactoryBeanClass);

    definition.getPropertyValues().add("addToConfig", this.addToConfig);

    boolean explicitFactoryUsed = false;
    if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
   
      definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
      explicitFactoryUsed = true;
    } else if (this.sqlSessionFactory != null) {
   
      definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
      explicitFactoryUsed = true;
    }

    if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
   
      if (explicitFactoryUsed) {
   
        LOGGER.warn(() -> "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
      }
      definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
      explicitFactoryUsed = true;
    } else if (this.sqlSessionTemplate != null) {
   
      if (explicitFactoryUsed) {
   
        LOGGER.warn(() -> "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
      }
      definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
      explicitFactoryUsed = true;
    }

    if (!explicitFactoryUsed) {
   
      LOGGER.debug(() -> "Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");
      // 设置根据类型注入
      definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
    }
  }
}

设置注入类型是根据类型注入

MapperFactoryBean集成SqlSessionDaoSupport类,SqlSessionDaoSupport中有setSqlSessionFactory方法,在Spring容器中能根据SqlSessionFactory类型找到类型匹配的类,所以注入SqlSessionFactory

public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
   
  if (this.sqlSessionTemplate == null || sqlSessionFactory != this.sqlSessionTemplate.getSqlSessionFactory()) {
   
    this.sqlSessionTemplate = createSqlSessionTemplate(sqlSessionFactory);
  }
}

源码解析

分析根据类型注入的源码

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);
   // 寻找bw中需要依赖注入的属性
   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.
         if (Object.class != pd.getPropertyType()) {
   
            // 获取指定属性的set方法,封装成MethodParameter(必须有set方法才能通过属性来注入)
            MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
            // Do not allow eager init for type matching in case of a prioritized post-processor.
            boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
            // 将MethodParameter的方法参数索引信息封装成DependencyDescriptor
            DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
            // 解析当前属性所匹配的bean实例,并把解析到的bean实例的beanName存储在autowiredBeanNames中
            Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
            if (autowiredArgument != null) {
   
               // 如果找到了依赖的bean实例,将属性名和bean实例放到pvs中
               pvs.add(propertyName, autowiredArgument);
            }
            for (String autowiredBeanName : autowiredBeanNames) {
   
               // 注册依赖关系,beanName依赖autowiredBeanName
               registerDependentBean(autowiredBeanName, beanName);
               if (logger.isDebugEnabled()) {
   
                  logger.debug("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);
      }
   }
}
  1. 得到需要依赖注入的属性:获取实例化的Bean中,写入属性值的方法(set方法)不为空 && pd不是从依赖性检查中排除的bean属性 && pd不包含在pvs里&& pd的属性类型不是“简单”属性(基础类型、枚举、Number等)的属性。
  2. 其中要注入的属性名称是:例如setXXX方法-setNam的名称是nam,根据nam从容器中获取Bean。
  3. 调用resolveDependency先根据要注入的属性类型存在多个再根据名称从Spring容器中获取要注入的Bean。
  4. 将要注入的属性加入到pvs中,之后再反射注入

详细分析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 Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
   }
   else {
   
      // 通用类注入的处理
      // 如有必要,请获取延迟解析代理
      Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
            descriptor, requestingBeanName);
      if (result == null) {
   
         // 解析依赖关系,返回的result为创建好的依赖对象的bean实例
         result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
      }
      return result;
   }
}

继续分析doResolveDependency

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值