Spring ④ Autowired 注解依赖注入详解

spring-logo.png

Spring ④ Autowired 注解依赖注入详解 | 看不懂你打我

Spring 源码系列文章会遵循由浅入深,由易到难,由宏观到微观的原则,目标是尽量降低学习难度,而不是一上来就迷失在源码当中. 文章会从一个场景作为出发点,针对性的目的性极强的针对该场景对 Spring 的实现原理,源码进行探究学习。该系列文章会让你收获什么? 从对 Spring 的使用者成为 Spring 专家。该文章会同步在微信公众号 【DevXJava】, 方便在微信客户端阅读。

本章的内容是对 bean 创建过程中依赖项注入的探究,为了不扩散问题域本章只针对 @Autowired 注解进行讲解分析。本章会讲解 构造器注入 属性注入 方法注入 Optional ObjectFactory ObjectProvider JSR330 类型的属性注入。方式遵循前几期,会通过最简单的案例场景带入去叫讲解 spring 的实现原理。

在开始今天的内容之前先回顾一下上期的内容, bean 的创建过程大致经历了三步, createBeanInstance 创建 bean 的实例对象。 populateBean 填充bean,依赖注入发生在这个阶段(大部分场景是,但一些特殊场景的依赖注入并不在这个阶段进行比如构造器注入)。 initializeBean 进行 bean 的一些初始化过程。了解了这个 bean 创建的大致过程会对读者理解本期的内容起帮助作用。

image.png

构造器注入

构造器注入过程发生在 bean 对象的实例化阶段,是和对象的实例化同时进行的,因为是通过构造器注入 bean 的实例化过程也是通过构造器。

构造器注入场景
public class AutowiredConstructorInjectionExp {

    public static void main(String[] args) {
        // 构造器注入

        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(factory);
        factory.addBeanPostProcessor(processor);

        factory.registerBeanDefinition("bean1" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean1.class)
                .getBeanDefinition());

        factory.registerBeanDefinition("bean2" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean2.class)
                .getBeanDefinition());

        Bean1 bean1 = factory.getBean(Bean1.class);
        System.out.println("bean1 -> " + bean1);
    }

    @Data
    static class Bean1 {

        Bean2 bean2;

        public Bean1(Bean2 bean2) {
            this.bean2 = bean2;
            System.out.println("======================== bean1 实例化");
        }
    }

    static class Bean2 {

        public Bean2() {
            System.out.println("++++++++++++++++++++++++++ bean2 实例化");
        }
    }
}
构造器注入 autowireConstructor

构造器注入的关键点在 determineConstructorsFromBeanPostProcessors autowireConstructor . 接下来会着重探讨这两个方法。

image.png

determineConstructorsFromBeanPostProcessors
/**
 * Determine candidate constructors to use for the given bean, checking all registered
 * {@link SmartInstantiationAwareBeanPostProcessor SmartInstantiationAwareBeanPostProcessors}.
 * @param beanClass the raw class of the bean
 * @param beanName the name of the bean
 * @return the candidate constructors, or {@code null} if none specified
 * @throws org.springframework.beans.BeansException in case of errors
 * @see org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
 */
@Nullable
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
      throws BeansException {

   if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
      for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
         Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName);
         if (ctors != null) {
            return ctors;
         }
      }
   }
   return null;
}

determineConstructorsFromBeanPostProcessors 中调用了 SmartInstantiationAwareBeanPostProcessor determineCandidateConstructors 方法。在场景代码中我们创建了 AutowiredAnnotationBeanPostProcessor 实例,并把它注册到 AbstractBeanFactory 中。这样就可以由它来起到探测构造器的功能。

image.png

determineConstructorsFromBeanPostProcessors 会得到多个构造器, autowireConstructor 会对这些构造器进行筛选找到一个合适匹配的构造器。

autowireConstructor
/**
 * "autowire constructor" (with constructor arguments by type) behavior.
 * Also applied if explicit constructor argument values are specified,
 * matching all remaining arguments with beans from the bean factory.
 * <p>This corresponds to constructor injection: In this mode, a Spring
 * bean factory is able to host components that expect constructor-based
 * dependency resolution.
 * @param beanName the name of the bean
 * @param mbd the bean definition for the bean
 * @param ctors the chosen candidate constructors
 * @param explicitArgs argument values passed in programmatically via the getBean method,
 * or {@code null} if none (implying the use of constructor argument values from bean definition)
 * @return a BeanWrapper for the new instance
 */
protected BeanWrapper autowireConstructor(
                String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {

    return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}

由于 ConstructorResolver 方法 autowireConstructor 源码较为繁琐就不进行逐一讲解,有兴趣的读者可以自己阅读源码。这里列出几个关键方法 ConstructorResolver#createArgumentArray , ConstructorResolver.resolveAutowiredArgument , AutowireCapableBeanFactory#resolveDependency , ConstructorResolver#instantiate 和说明简图方便读者阅读源码时有针对性的查看。

image.png

AutowiredAnnotationBeanPostProcessor

在讲解 属性注入 方法注入 前我们先认识一下 AutowiredAnnotationBeanPostProcessor bean 后置处理器 , @Autowired 注解之所以可以起作用就是因为它在背后提供支持。 AutowiredAnnotationBeanPostProcessor 实现了很多的 bean 后置处理器接口,其中有一个方法 InstantiationAwareBeanPostProcessor#postProcessProperties 我们会着重进行讲解,它是和依赖注入密不可分的。

通过 AutowiredAnnotationBeanPostProcessor 完成依赖注入的都是发生在 populateBean 阶段(也就是 bean 的填充阶段)。

image.png

属性注入和方法注入

属性注入和方法注入十分的类似可以放在一起讲解。

属性注入场景

public class AutowiredFieldInjectionExp {

    public static void main(String[] args) {

        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(factory);
        factory.addBeanPostProcessor(processor);

        factory.registerBeanDefinition("bean1" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean1.class)
                .getBeanDefinition());

        factory.registerBeanDefinition("bean2" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean2.class)
                .getBeanDefinition());

        Bean1 bean1 = factory.getBean(Bean1.class);
        System.out.println("bean1 -> " + bean1);

    }

    @Data
    static class Bean1 {

        @Autowired
        Bean2 bean2;

        public Bean1() {
            System.out.println("======================== bean1 实例化");
        }
    }

    static class Bean2 {

        public Bean2() {
            System.out.println("++++++++++++++++++++++++++ bean2 实例化");
        }
    }

}

方法注入场景

public class AutowiredMethodInjectionExp {

    public static void main(String[] args) {

        // 方法注入
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(factory);
        factory.addBeanPostProcessor(processor);

        factory.registerBeanDefinition("bean1" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean1.class)
                .getBeanDefinition());

        factory.registerBeanDefinition("bean2" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean2.class)
                .getBeanDefinition());

        Bean1 bean1 = factory.getBean(Bean1.class);
        System.out.println("bean1 -> " + bean1);
    }

    @ToString
    static class Bean1 {

        Bean2 bean2;

        @Autowired
        public void setBean2(Bean2 bean2) {
            this.bean2 = bean2;
        }
    }

    static class Bean2 {

        public Bean2() {
            System.out.println("++++++++++++++++++++++++++ bean2 实例化");
        }
    }
}

对源码 debug 我们可以发现在执行 AutowiredAnnotationBeanPostProcessor#postProcessProperties 之前 Bean1 中的 bean2 属性为 null . 并且 instantiationAware 中只有一个元素 AutowiredAnnotationBeanPostProcessor 对象. 我们已经尽可能的排除了干扰.

image.png

在执行了 AutowiredAnnotationBeanPostProcessor#postProcessProperties 之后 bean2 属性已经有值了. 接下来我们会重点看 postProcessProperties 方法中都做了什么。

image.png

AutowiredAnnotationBeanPostProcessor#postProcessProperties

image.png

@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;
}
findAutowiringMetadata
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)) {
            if (metadata != null) {
               metadata.clear(pvs);
            }
            metadata = buildAutowiringMetadata(clazz);
            this.injectionMetadataCache.put(cacheKey, metadata);
         }
      }
   }
   return metadata;
}
buildAutowiringMetadata
private InjectionMetadata buildAutowiringMetadata(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);
}
InjectionMetadata#inject

不同的注入元素有不同的注入方式实现, 属性注入 AutowiredFieldElement , 方法注入 AutowiredMethodElement .

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
   Collection<InjectedElement> checkedElements = this.checkedElements;
   Collection<InjectedElement> elementsToIterate =
         (checkedElements != null ? checkedElements : this.injectedElements);
   if (!elementsToIterate.isEmpty()) {
      for (InjectedElement element : elementsToIterate) {
         element.inject(target, beanName, pvs);
      }
   }
}
AutowiredFieldElement#inject
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
   Field field = (Field) this.member;
   Object value;
   if (this.cached) {
      try {
         value = resolvedCachedArgument(beanName, this.cachedFieldValue);
      }
      catch (NoSuchBeanDefinitionException ex) {
         // Unexpected removal of target bean for cached argument -> re-resolve
         value = resolveFieldValue(field, bean, beanName);
      }
   }
   else {
      value = resolveFieldValue(field, bean, beanName);
   }
   if (value != null) {
      ReflectionUtils.makeAccessible(field);
      field.set(bean, value);
   }
}
AutowiredMethodElement#inject
@Override
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
   if (checkPropertySkipping(pvs)) {
      return;
   }
   Method method = (Method) this.member;
   Object[] arguments;
   if (this.cached) {
      try {
         arguments = resolveCachedArguments(beanName);
      }
      catch (NoSuchBeanDefinitionException ex) {
         // Unexpected removal of target bean for cached argument -> re-resolve
         arguments = resolveMethodArguments(method, bean, beanName);
      }
   }
   else {
      arguments = resolveMethodArguments(method, bean, beanName);
   }
   if (arguments != null) {
      try {
         ReflectionUtils.makeAccessible(method);
         method.invoke(bean, arguments);
      }
      catch (InvocationTargetException ex) {
         throw ex.getTargetException();
      }
   }
}

Optional ObjectFactory ObjectProvider JSR330 类型的注入

由于这部分较为简单容易理解就只做简单介绍。其中 ObjectFactory ObjectProvider JSR330 这三类其实是起到了延迟加载的作用。核心代码在 org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency 方法。

场景

public class AutowiredOtherTypeInjectionExp {

    public static void main(String[] args) {
        // `Optional` 、`ObjectFactory` 、`ObjectProvider` 、`JSR330` 类型的注入

        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

        AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
        processor.setBeanFactory(factory);
        factory.addBeanPostProcessor(processor);

        factory.registerBeanDefinition("bean1" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean1.class)
                .getBeanDefinition());

        factory.registerBeanDefinition("bean2" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean2.class)
                .getBeanDefinition());

        factory.registerBeanDefinition("bean3" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean3.class)
                .getBeanDefinition());

        factory.registerBeanDefinition("bean4" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean4.class)
                .getBeanDefinition());

        factory.registerBeanDefinition("bean5" , BeanDefinitionBuilder
                .genericBeanDefinition(Bean5.class)
                .getBeanDefinition());

        Bean1 bean1 = factory.getBean(Bean1.class);
        System.out.println("bean1 -> " + bean1);
    }

    @Data
    static class Bean1 {

        @Autowired
        Optional<Bean2> bean2;

        @Autowired
        ObjectFactory<Bean3> bean3;

        @Autowired
        ObjectProvider<Bean4> bean4;

        @Autowired
        Provider<Bean5> bean5;

        public Bean1() {
            System.out.println("======================== bean1 实例化");
        }
    }

    static class Bean2 {

        public Bean2() {
            System.out.println("++++++++++++++++++++++++++ bean2 实例化");
        }
    }

    static class Bean3 {
        public Bean3() {
            System.out.println("++++++++++++++++++++++++++ Bean3 实例化");
        }
    }

    static class Bean4 {
        public Bean4() {
            System.out.println("++++++++++++++++++++++++++ Bean4 实例化");
        }
    }

    static class Bean5 {
        public Bean5() {
            System.out.println("++++++++++++++++++++++++++ Bean5 实例化");
        }
    }
}

DefaultListableBeanFactory#resolveDependency

@Override
@Nullable
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 Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
   }
   else {
      Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
            descriptor, requestingBeanName);
      if (result == null) {
         result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
      }
      return result;
   }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值