关于java:Spring-Autowired-注解自动注入流程是怎么样

2次阅读

共计 10868 个字符,预计需要花费 28 分钟才能阅读完成。

面试中碰到面试官问:”Spring 注解是如果工作的?“,以后我一惊,完了这不涉及到我的常识误区了吗?,还好我机智,眉头一皱; 计上心来回了句:Spring 注解的工作流程倒还没有看到,然而我晓得 @Autowired 注解的工作流程,前面不用说了一顿巴拉,面试官都连连拍板。

面试中要活用转移话题,要防止答复”不晓得“,要疏导面试官掉入你善于的技术,而后才有机会教他作人。

@Autowired 相干的类

@Autowired 注解的次要性能就是实现主动注入,应用也非常简单(Spring 都安顿好了),然而要想晓得 @Autowired 注解的外部事实,就须要看一下 Spring 源码了。接下来一步步的解剖 @Autowired 的实现原理,首先理一下与 @Autowired 注解相干的类,而后一步步的跟踪源码,直到了解 @Autowired 的原理。

AutowiredAnnotationBeanPostProcessor 类

AutowiredAnnotationBeanPostProcessor是实现 @Autowired 性能的次要类,它有一些办法是会用解析 @Autowired 注解并实现主动注入的性能,上面是它的继承图:

从上图能够发现 AutowiredAnnotationBeanPostProcessor 最上层是 BeanPostProcessor 是一个后处理器,当然除了后处理器外两头还有 InstantiationAwareBeanPostProcessorMergedBeanDefinitionPostProcessor

InstantiationAwareBeanPostProcessor 接口

postProcessBeforeInstantiation 办法

在 Bean 实例化之前调用,能够返回一个 Bean 实例,默认返回null

@Nullabledefault Object postProcessBeforeInstantiation(Class<?> beanClass, String 
beanName) throws BeansException {return null;}

postProcessAfterInstantiation 办法

在 Bean 创立实现后,设置属性之前调用。

default boolean postProcessAfterInstantiation(Object bean, String 
beanName) throws BeansException {return true;}

postProcessProperties 办法

@Nullable default PropertyValues postProcessProperties(PropertyValues pvs, Object 
bean, String beanName)            throws BeansException {return null;}

Bean 创立完后,设置属性之前调用

先记住 InstantiationAwareBeanPostProcessor 接口,前面会跟踪调用它的中央,就很容易了解了。

MergedBeanDefinitionPostProcessor

MergedBeanDefinitionPostProcessor 也是一个继承 BeanPostProcessor 接口的后处理器,它的次要作用就是能够解决操作 BeanDefinition 对象,因为 Bean 的实例化是通过 BeanDefinition 的,通过操作 BeanDefinition,这样能够使 Bean 的实例化时产生一些变动。

MergedBeanDefinitionPostProcessor 只有两个办法

postProcessMergedBeanDefinition 办法

void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, 
Class<?> beanType, String beanName);

Bean 的 BeanDefinition 被合并后调用此办法。

resetBeanDefinition

default void resetBeanDefinition(String beanName) {}

当一个 BeanDefinition 被重置后调用。

AutowireCapableBeanFactory 接口

AutowireCapableBeanFactory继承自 BeanFactory,除了提供根底的 Bean 操作外,从接口的名字就能够推断出的它还有 主动注入 的能力。AutowireCapableBeanFactory 提供四种注入模型:

  • AUTOWIRE_NO:没有显示的定义注入模型
  • AUTOWIRE_BY_NAME:通过 Bean 名称注入
  • AUTOWIRE_BY_TYPE:通过 Bean 的类型注入
  • AUTOWIRE_CONSTRUCTOR:通过 Bean 的构造方法注入

AutowireCapableBeanFactory 接口有不少办法,但大部分都是跟主动注入的相干。@Autowired 的次要性能就是在 Bean 实例化后,为其设置属性,所以在 AutowireCapableBeanFactory 接口有一个 createBean 办法,用于创立 Bean 并设置 Bean 的属性:

<T> T createBean(Class<T> beanClass) throws BeansException;

createBean办法,它的调用机会是创立 Bean 的时候,稍后会说到它的调用机会。

AbstractAutowireCapableBeanFactory

AbstractAutowireCapableBeanFactory 继承 AbstractBeanFactory并实现了 AutowireCapableBeanFactory 接口,所以它也实现了 AutowireCapableBeanFactory 中的 createBean 办法。

public <T> T createBean(Class<T> beanClass) throws BeansException {     

// Use prototype bean definition, to avoid registering bean as dependent bean.      

RootBeanDefinition bd = new RootBeanDefinition(beanClass);      
bd.setScope(SCOPE_PROTOTYPE);     

bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader());      

return (T) createBean(beanClass.getName(), bd, null);}

Bean 创立的生命周期

通过理解 Bean 创立的生命周期,才能够将下面与 @Autowired 相干的类串起来,首先这里不会过多的介绍 Bean 的创立细节,只关注主动注入相干的代码。

Bean 的创立过程

Spring 中默认的 Bean 都是懒加载的,所以一个 Bean 的创立会从调用 getBean 办法开始,如果不思考缓存、下层容器的状况,Bean 的创立会通过以下办法:

  • getBean:BeanFactory 的办法,获取 Bean 实例
  • doGetBean:获取 Bean 的实例,获取程序顺次为:单例池、父容器,如果从以上 2 种路径都没获取到 Bean 实例就会创立新的
  • createBean:创立 Bean,这里的 createBean,跟下面介绍的是一回事
  • doCreateBean:创立 Bean 实例
  • populateBean:设置 Bean 属性

以上流程中的 getBeandoGetBean不多作阐明了,重点关注 createBean 后面提到 AbstractAutowireCapableBeanFactory.createBean 办法,所以说你在调用 getBean 办法获取 Bean 的实例时,如果这个 Bean 实例还没有被创立,那么 createBean 就会被调用。

通过简略的阐明 Bean 创立的生命周期,就能找到 @Autowired 注解实现的入口,接下来再持续跟踪 createBean 办法。

收集注入元信息

收集注入元信息的步骤的,其实就是调用 AutowiredAnnotationBeanPostProcessor 类办法来实现的。

Bean 创立之前

以下是 createBean 办法,在 Bean 创立之前调用 postProcessBeforeInstantiation 的中央。为是浏览不便省略了一些代码,大抵的流程就是:

  • 首先调用 resolveBeforeInstantiation 办法,执行 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation办法
  • 如果 postProcessBeforeInstantiation 返回 Bean 实例那么间接返回这个实例,如果返回 nul 持续调用doCreateBean
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
 
   ...

   try {
      // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
      if (bean != null) {return bean;}
   }
   catch (Throwable ex) {...}
   
     ...
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    ...
   
   ...
 }
   
 @Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
   Object bean = null;
   if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
      // Make sure bean class is actually resolved at this point.
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {Class<?> targetType = determineTargetType(beanName, mbd);
         if (targetType != null) {bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
            if (bean != null) {bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
            }
         }
      }
      mbd.beforeInstantiationResolved = (bean != null);
   }
   return bean;
}

这里 AutowiredAnnotationBeanPostProcessor 的 postProcessBeforeInstantiation 的办法会被调用,因为 AutowiredAnnotationBeanPostProcessor 并没有重写这个办法,所以什么都不做。

操作 BeanDefinition

下面说过 postProcessBeforeInstantiation 办法返回 null 的话会继续执行 doCreateBean 办法:

 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {


   // Allow post-processors to modify the merged bean definition.
   synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {
         try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         }
         mbd.postProcessed = true;
      }
   }

  ...
 populateBean(beanName, mbd, instanceWrapper);
 ...
 

在 doCreateBean 办法中,会调用调用 applyMergedBeanDefinitionPostProcessors 办法:

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof MergedBeanDefinitionPostProcessor) {MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
         bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
      }
   }

MergedBeanDefinitionPostProcessor接口下面提到到的,AutowiredAnnotationBeanPostProcessor 实现了这个接口所以间接进入到 AutowiredAnnotationBeanPostProcessor 中的 postProcessMergedBeanDefinition办法:


@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
   metadata.checkConfigMembers(beanDefinition);
}
查找注入元数据

接着持续进入到 findAutowiringMetadata,findAutowiringMetadata 会调用buildAutowiringMetadata 办法创立注入元数据,而后将元数据缓存到 injectionMetadataCache 属性中:


private InjectionMetadata findAutowiringMetadata(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);
   if (InjectionMetadata.needsRefresh(metadata, clazz)) {synchronized (this.injectionMetadataCache) {metadata = this.injectionMetadataCache.get(cacheKey);
         if (InjectionMetadata.needsRefresh(metadata, clazz)) {
            ...
            metadata = buildAutowiringMetadata(clazz);
            this.injectionMetadataCache.put(cacheKey, metadata);
         }
      }
   }
   return metadata;
}
创立注入元数据

认真查看 buildAutowiringMetadata 办法的实现,它会反射类的办法和属性,同时还会向上查找父类,而后生成InjectionMetadata

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {return InjectionMetadata.EMPTY;}

        List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
        Class<?> targetClass = clazz;

        do {final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

            ReflectionUtils.doWithLocalFields(targetClass, field -> {MergedAnnotation<?> ann = findAutowiredAnnotation(field);
                if (ann != null) {if (Modifier.isStatic(field.getModifiers())) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation is not supported on static fields:" + field);
                        }
                        return;
                    }
                    boolean required = determineRequiredStatus(ann);
                    currElements.add(new AutowiredFieldElement(field, required));
                }
            });

            ReflectionUtils.doWithLocalMethods(targetClass, method -> {Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
                if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {return;}
                MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
                if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {if (Modifier.isStatic(method.getModifiers())) {if (logger.isInfoEnabled()) {logger.info("Autowired annotation is not supported on static methods:" + method);
                        }
                        return;
                    }
                    if (method.getParameterCount() == 0) {if (logger.isInfoEnabled()) {
                            logger.info("Autowired annotation should only be used on methods with parameters:" +
                                    method);
                        }
                    }
                    boolean required = determineRequiredStatus(ann);
                    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
                    currElements.add(new AutowiredMethodElement(method, required, pd));
                }
            });

            elements.addAll(0, currElements);
            targetClass = targetClass.getSuperclass();}
        while (targetClass != null && targetClass != Object.class);

        return InjectionMetadata.forElements(elements, clazz);
    }

小结

收集注入元数据过程,首先调用 AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition 办法,而后调用 findAutowiringMetadata 办法查找元数据,如果找到相应类的注入元数据,就会调用 buildAutowiringMetadata 办法创立 InjectionMetadata,最初将新创建的注入元数据保留在injectionMetadataCache 缓存起来。

设置 Bean 属性

收信完注入元数据后,Bean 的属性还是没有注入的,还须要将执行属性注入。还是在 doCreateBean 办法中,收集完注入元数据后,紧接着会调用populateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();
   }
   for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
         PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
         if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }
            pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {return;}
         }
         pvs = pvsToUse;
      }
   }
   }
}

能够看到在 populateBean 中会调用 InstantiationAwareBeanPostProcessor.postProcessProperties 办法,因为曾经晓得 AutowiredAnnotationBeanPostProcessor 是实现 InstantiationAwareBeanPostProcessor 的,所以能够间接查看实现办法:

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

postProcessProperties就很简略的,查找 InjectMetadata,而后调用 InjectMetadata.inject办法。到这里其实就曾经晓得 @Autowire 的实现机制了,接下来就是依据 InjectionMetadata 中的信息实现属性注入了。

如果须要深入研究的话,有趣味的还能够持续往下看。

总结

本文大抵解说了 @Autowire 相干的类与实现的机制,@Autowire 注解的实现次要是了解 AutowiredAnnotationBeanPostProcessor 类,还有收集注入元数据、设置注入属性的调用机会。

通过查看 AutowiredAnnotationBeanPostProcessor 类源码,置信你也能够自定义注入性能。

自己常识程度无限,如有谬误,谢谢大家斧正。

欢送关注我的公众号:架构文摘,取得独家整顿 120G 的收费学习资源助力你的架构师学习之路!

公众号后盾回复 arch028 获取材料:

正文完
 0