Java Spring
@Autowired注解的实现过程,其实就是Spring Bean的自动装配过程。通过看@Autowired源码注释部分可以看到@Autowired的实现是通过AutowiredAnnotationBeanPostProcessor后置处理器中实现的。

AutowiredAnnotationBeanPostProcessor 类图

image.png

  • PriorityOrdered:确认 AutowiredAnnotationBeanPostProcessor 后置处理器的执行优先级
  • BeanFactoryAware:使得AutowiredAnnotationBeanPostProcessor可以直接通过BeanFactory获取容器中的Bean
  • BeanPostProcessor:在 Bean 初始化前后执行的后置处理器
  • InstantiationAwareBeanPostProcessor:在 Bean 实例化前后和Bean设置属性值时执行的后置处理器
  • SmartInstantiationAwareBeanPostProcessor:智能实例化Bean的后处理器,如预测Bean的类型和确认Bean的构造函数等。
  • MergedBeanDefinitionPostProcessor:合并Bean的定义信息。

在分析自动装配前先来介绍一下上面的这些后置处理器。

后置处理器介绍

BeanPostProcessor

BeanPostProcessor有两个方法,postProcessBeforeInitializationpostProcessAfterInitialization。它们分别在任何Bean初始化回调之前或之后执行(例如InitializingBean的afterPropertiesSet方法或自定义init-method方法之前或者之后), 在这个时候该bean的属性值已经填充完成了,并且返回的Bean实例可能已经是原始实例的包装类型了。例如返回一个FactoryBean

InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor继承自BeanPostProcessor接口。主要多提供了以下三个方法。

postProcessBeforeInstantiation

该方法是在Bean实例化目标对象之前调用,返回的Bean对象可以代理目标,从而有效的阻止了目标Bean的默认实例化。

  1. protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
  2. Object bean = null;
  3. if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
  4. // Make sure bean class is actually resolved at this point.
  5. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  6. Class<?> targetType = determineTargetType(beanName, mbd);
  7. if (targetType != null) {
  8. bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
  9. if (bean != null) {
  10. // 如果此方法返回一个非null对象,则Bean创建过程将被短路。
  11. // 唯一应用的进一步处理是来自已配置BeanPostProcessors的postProcessAfterInitialization回调
  12. bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
  13. }
  14. }
  15. }
  16. mbd.beforeInstantiationResolved = (bean != null);
  17. }
  18. return bean;
  19. }
  20. protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
  21. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  22. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  23. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  24. // 执行Bean实例化目标对象之前的后置处理方法
  25. Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
  26. if (result != null) {
  27. return result;
  28. }
  29. }
  30. }
  31. return null;
  32. }

跟进源码可以看出,如果此方法返回一个非null对象,则Bean创建过程将被短路。唯一应用的进一步处理是来自已配置BeanPostProcessors的postProcessAfterInitialization回调。

postProcessAfterInstantiation

该方法执行在通过构造函数或工厂方法在实例化bean之后但在发生Spring属性填充(通过显式属性或自动装配)之前执行操作。这是在Spring的自动装配开始之前对给定的bean实例执行自定义字段注入的理想回调。如果该方法返回false,那么它会阻断后续InstantiationAwareBeanPostProcessor后置处理器的执行,并且会阻止后续属性填充的执行逻辑。

postProcessPropertyValues

在工厂将给定属性值应用于给定bean之前,对它们进行后处理。允许检查是否满足所有依赖关系,例如基于bean属性设置器上的“ Required”注解。还允许替换要应用的属性值,通常是通过基于原始PropertyValues创建新的MutablePropertyValues实例,添加或删除特定值来实现。

SmartInstantiationAwareBeanPostProcessor

智能实例化Bean的后处理器,主要提供了三个方法。

predictBeanType

预测从此处理器的postProcessBeforeInstantiation回调最终返回的bean的类型。

determineCandidateConstructors

确定使用实例化Bean的构造函数。

getEarlyBeanReference

获取提早暴露的Bean的引用,提早暴露的Bean就是只完成了实例化,还未完成属性赋值和初始化的Bean。

MergedBeanDefinitionPostProcessor

postProcessMergedBeanDefinition

合并Bean的定义信息的后处理方法,该方法是在Bean的实例化之后设置值之前调用。

自动装配的实现

找到需要自动装配的元素

AutowiredAnnotationBeanPostProcessor后置处理器主要负责对添加了@Autowired@Value注解的元素实现自动装配。所以找到需要自动装配的元素,其实就是对@Autowired@Value注解的解析。
AutowiredAnnotationBeanPostProcessor后置处理器,找出需要自动装配的元素是在MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition这个方法中实现的,调用链路如下:

  1. doWith:445, AutowiredAnnotationBeanPostProcessor$2 (org.springframework.beans.factory.annotation)
  2. doWithLocalFields:657, ReflectionUtils (org.springframework.util)
  3. buildAutowiringMetadata:433, AutowiredAnnotationBeanPostProcessor (org.springframework.beans.factory.annotation)
  4. findAutowiringMetadata:412, AutowiredAnnotationBeanPostProcessor (org.springframework.beans.factory.annotation)
  5. postProcessMergedBeanDefinition:235, AutowiredAnnotationBeanPostProcessor (org.springframework.beans.factory.annotation)
  6. applyMergedBeanDefinitionPostProcessors:1000, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
  7. doCreateBean:523, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
  8. createBean:483, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
  9. getObject:312, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
  10. getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
  11. doGetBean:308, AbstractBeanFactory (org.springframework.beans.factory.support)
  12. getBean:197, AbstractBeanFactory (org.springframework.beans.factory.support)
  13. preInstantiateSingletons:761, DefaultListableBeanFactory (org.springframework.beans.factory.support)
  14. finishBeanFactoryInitialization:867, AbstractApplicationContext (org.springframework.context.support)
  15. refresh:543, AbstractApplicationContext (org.springframework.context.support)
  16. <init>:84, AnnotationConfigApplicationContext (org.springframework.context.annotation)

从链路上可以看到,找到需要自动装配的元素是在findAutowiringMetadata方法中实现的,该方法会去调用buildAutowiringMetadata方法构建元数据信息。如果注解被加载属性上将会被封装成AutowiredFieldElement对象;如果注解加在方法上,那么元素会被封装成AutowiredMethodElement对象。这里两个对象的inject方法将最后完成属性值的注入,主要区别就是使用反射注入值的方式不一样。源码如下:

  1. private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
  2. LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
  3. Class<?> targetClass = clazz;
  4. do {
  5. // 存放找到的元数据信息
  6. final LinkedList<InjectionMetadata.InjectedElement> currElements =
  7. new LinkedList<InjectionMetadata.InjectedElement>();
  8. // 通过反射找出对应Class对象的所有Field
  9. ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {
  10. @Override
  11. public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
  12. // 通过反射找到该字段上所有的注解信息,并判断是否有@Autowired和@Value注解,如果有就将该字段封成AutowiredFieldElement对象
  13. AnnotationAttributes ann = findAutowiredAnnotation(field);
  14. if (ann != null) {
  15. if (Modifier.isStatic(field.getModifiers())) {
  16. if (logger.isWarnEnabled()) {
  17. logger.warn("Autowired annotation is not supported on static fields: " + field);
  18. }
  19. return;
  20. }
  21. boolean required = determineRequiredStatus(ann);、
  22. // 将该字段封成AutowiredFieldElement对象,并放到缓存中
  23. currElements.add(new AutowiredFieldElement(field, required));
  24. }
  25. }
  26. });
  27. // 通过反射找出对应Class对象的所有Method
  28. ReflectionUtils.doWithLocalMethods(targetClass, new ReflectionUtils.MethodCallback() {
  29. @Override
  30. public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
  31. Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
  32. if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
  33. return;
  34. }
  35. // 通过反射找到该字段上所有的注解信息,并判断是否有@Autowired和@Value注解,如果有就将该字段封成AutowiredMethodElement对象
  36. AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
  37. if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
  38. if (Modifier.isStatic(method.getModifiers())) {
  39. if (logger.isWarnEnabled()) {
  40. logger.warn("Autowired annotation is not supported on static methods: " + method);
  41. }
  42. return;
  43. }
  44. if (method.getParameterTypes().length == 0) {
  45. if (logger.isWarnEnabled()) {
  46. logger.warn("Autowired annotation should only be used on methods with parameters: " +
  47. method);
  48. }
  49. }
  50. boolean required = determineRequiredStatus(ann);
  51. PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
  52. // 将该字段封成AutowiredMethodElement对象
  53. currElements.add(new AutowiredMethodElement(method, required, pd));
  54. }
  55. }
  56. });
  57. elements.addAll(0, currElements);
  58. targetClass = targetClass.getSuperclass();
  59. }
  60. // 循环处理父类需要自动装配的元素
  61. while (targetClass != null && targetClass != Object.class);
  62. // 将需要自动装配的元素封装成InjectionMetadata对象,最后合并到Bean定义中
  63. return new InjectionMetadata(clazz, elements);
  64. }

寻找需要自动装配过程:

  1. 根据Class对象,通过反射获取所有的FieldMethod对象
  2. 通过反射获取FieldMethod上的注解,并判断是否有@Autowired@Value注解
  3. 将注解了@Autowired@ValueFieldMethod封装成AutowiredFieldElementAutowiredMethodElement对象,等待下一步的自动装配。
  4. 循环处理父类需要自动装配的元素
  5. 将需要自动装配的元素封装成InjectionMetadata对象,最后合并到Bean定义的externallyManagedConfigMembers属性中

    注入属性值

    AutowiredAnnotationBeanPostProcessor后置处理器注入属性值是在postProcessPropertyValues方法中实现的。源码如下:

    1. public void inject(Object target, String beanName, PropertyValues pvs) throws Throwable {
    2. // 获取需要自动装配的元数据信息(这里实在缓存中取)
    3. Collection<InjectedElement> elementsToIterate =
    4. (this.checkedElements != null ? this.checkedElements : this.injectedElements);
    5. if (!elementsToIterate.isEmpty()) {
    6. boolean debug = logger.isDebugEnabled();
    7. for (InjectedElement element : elementsToIterate) {
    8. if (debug) {
    9. logger.debug("Processing injected element of bean '" + beanName + "': " + element);
    10. }
    11. // 调用AutowiredFieldElement或AutowiredMethodElement对象的inject方法注入属性值
    12. element.inject(target, beanName, pvs);
    13. }
    14. }
    15. }

    AutowiredFieldElement#inject

    1. @Override
    2. protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
    3. Field field = (Field) this.member;
    4. Object value;
    5. if (this.cached) {
    6. value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    7. }
    8. else {
    9. DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
    10. desc.setContainingClass(bean.getClass());
    11. Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
    12. TypeConverter typeConverter = beanFactory.getTypeConverter();
    13. try {
    14. // 在容器中获取需要装配的Bean
    15. value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    16. }
    17. ...
    18. }
    19. if (value != null) {
    20. // 通过反射设置属性值
    21. ReflectionUtils.makeAccessible(field);
    22. field.set(bean, value);
    23. }
    24. }

    AutowiredMethodElement#inject

    1. @Override
    2. protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
    3. if (checkPropertySkipping(pvs)) {
    4. return;
    5. }
    6. Method method = (Method) this.member;
    7. Object[] arguments;
    8. if (this.cached) {
    9. // Shortcut for avoiding synchronization...
    10. arguments = resolveCachedArguments(beanName);
    11. }
    12. else {
    13. Class<?>[] paramTypes = method.getParameterTypes();
    14. arguments = new Object[paramTypes.length];
    15. DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
    16. Set<String> autowiredBeans = new LinkedHashSet<String>(paramTypes.length);
    17. TypeConverter typeConverter = beanFactory.getTypeConverter();
    18. for (int i = 0; i < arguments.length; i++) {
    19. MethodParameter methodParam = new MethodParameter(method, i);
    20. DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
    21. currDesc.setContainingClass(bean.getClass());
    22. descriptors[i] = currDesc;
    23. try {
    24. // 在容器中获取需要装配的Bean
    25. Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
    26. if (arg == null && !this.required) {
    27. arguments = null;
    28. break;
    29. }
    30. arguments[i] = arg;
    31. }
    32. catch (BeansException ex) {
    33. throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
    34. }
    35. }
    36. ...
    37. }
    38. if (arguments != null) {
    39. try {
    40. // 通过反射调用方法设置元素值
    41. ReflectionUtils.makeAccessible(method);
    42. method.invoke(bean, arguments);
    43. }
    44. ...
    45. }
    46. }

    从这里的源码可以看出AutowiredFieldElementAutowiredMethodElement完成自动装配都是先去容器中找对应的Bean,然后通过反射将获取到的Bean设置到目标对象中,来完成Bean的自动装配。

    总结

    可以看出Spring Bean的自动装配过程就是:

  6. 根据Class对象,通过反射获取所有的FieldMethod信息

  7. 通反射获取FieldMethod的注解信息,并根据注解类型,判断是否需要自动装配
  8. 将需要自动装配的元素,封装成AutowiredFieldElementAutowiredMethodElement对象
  9. 调用AutowiredFieldElementAutowiredMethodElementinject方法,唤起后续步骤
  10. 通过调用容器的getBean()方法找到需要注入的源数据Bean
  11. 通过反射将找到的源数据Bean注入到目标Bean中

在自动装配过程中还涉及循环依赖的问题。 :::tips 注意:注解注入将在XML注入之前执行;因此,对于通过这两种方法注入的属性,XML注入将覆盖注解注入。 :::