Spring 依赖注入源码

发布时间:2023-12-25 11:49:18

依赖注入

具体代码是在AbstractAutowireCapableBeanFactory类的populateBean()方法,此方法中主要做的事情如下:

  • 实例化之后,调用InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation方法
  • Spring早期通过BY_NAME或BY_TYPE两种方式,并利用set方法进行依赖注入
  • 通过InstantiationAwareBeanPostProcessor接口的postProcessProperties()方法进行依赖注入,典型的代表就是@Autowired等注解的处理
  • 将BeanDefinition中的PropertyValues覆盖@Autowired等注解的值



原始依赖注入方式

在线流程图

在这里插入图片描述


首先分析Spring早期的依赖注入

@Bean(autowire = Autowire.BY_NAME)
public UserService userService(){
   
   return new UserService();
}

接下来就会遍历UserService中所有的set方法进行依赖注入。

对应的Spring源码是

PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
// 必须是BY_NAME或BY_TYPE
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
   
   // MutablePropertyValues是PropertyValues具体的实现类
   MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
   // 这里会根据我们的配置来分别调用不同的方法
   if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
   
      autowireByName(beanName, mbd, bw, newPvs);
   }
   if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
   
      autowireByType(beanName, mbd, bw, newPvs);
   }
   pvs = newPvs;
}

接下来看autowireByName()方法,主要过程就是先根据set方法找出所有的属性名,然后在遍历属性名集合,去单例池中找,再赋值给pvs变量

protected void autowireByName(
      String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
   

   // 当前Bean中能进行自动注入的属性名,是根据setXXX()方法生成是属性名
   String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
   // 遍历每个属性名,并去获取Bean对象,并设置到pvs中
   for (String propertyName : propertyNames) {
   
      // 要进行依赖注入的属性在当前容器中是否存在
      if (containsBean(propertyName)) {
   
         // 从容器中取出来,再存入pvs中
         Object bean = getBean(propertyName);
         pvs.add(propertyName, bean);
         // 记录一下propertyName对应的Bean被beanName给依赖了
         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");
         }
      }
   }
}

autowireByType()方法其实也类似,首先得到属性名集合,再遍历集合,然后得到方法形参的类型,根据resolveDependency()找到bean对象,再存入pvs



注解方式

在线流程图

在这里插入图片描述


我们常用的方式是利用@Autowired等注解的方式实现依赖注入的,在Spring源码AbstractAutowireCapableBeanFactory类的populateBean()方法中对应的实现其实就是利用InstantiationAwareBeanPostProcessor接口的postProcessProperties()方法实现的

for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
   
   // @Autowired注解 这里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,会直接给对象中的属性赋值
   // AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
   PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
   if (pvsToUse == null) {
   
      if (filteredPds == null) {
   
         filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
      }
      pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
      if (pvsToUse == null) {
   
         return;
      }
   }
   pvs = pvsToUse;
}

@Autowired@Value注解是通过AutowiredAnnotationBeanPostProcessor类处理的

@Resource注解是通过CommonAnnotationBeanPostProcessor类处理的


实现看AutowiredAnnotationBeanPostProcessor类的定义,它实现了初始化后置处理器以及BeanDefinition后置处理器两个接口,所以该类就会有下面两个方法

InstantiationAwareBeanPostProcessor接口的postProcessProperties()方法

MergedBeanDefinitionPostProcessor接口的postProcessMergedBeanDefinition()方法

public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor,
      MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
   
          ...
}

根据我们对Bean生命周期的了解可以知道,postProcessMergedBeanDefinition()方法先执行,postProcessProperties()方法后执行



寻找注入点

我们可以先想一想如果要自己实现依赖注入应该要怎么做?首先就是找出类里面所有加了@Autowired注解的属性和Set方法,这个也称为注入点,然后在为这些注入点赋值。接下来看具体的实现,首先的BeanDefinition的后置处理器方法

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
   
   // 根据类的class对象找到所有的注入点
   InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
   metadata.checkConfigMembers(beanDefinition);
}

先看findAutowiringMetadata()方法逻辑

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
   
   // cacheKey其实就beanName
   String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
   // 该类的所有注入点会缓存到injectionMetadataCache中
   InjectionMetadata metadata = this.injectionMetadataCache.get(
文章来源:https://blog.csdn.net/qq_44027353/article/details/130451172
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。