SpringBoot 注解 @Value 实现源码分析

我就是我 2023-10-02 11:56 87阅读 0赞

文章目录

  • 前言
    1. @Value 的源码处理流程
    1. 源码分析
      • 2.1 后置处理器 AutowiredAnnotationBeanPostProcessor 的注册
      • 2.2 属性处理器 PropertySourcesPropertyResolver 的注册
      • 2.3 @Value 标注字段的依赖处理

前言

SpringBoot 提供了很多开箱即用的实用工具,比如我们可以使用 @Value 注解获取容器中的配置数据,自动完成属性的赋值,本文即从源码角度来解析 @Value 的实现机制

1. @Value 的源码处理流程

@Value 实现属性注入的源码流程如下图所示,笔者将其从组件的准备组件的使用分为了三个部分:

  1. @Value 后置处理器 AutowiredAnnotationBeanPostProcessor 的注册,这个后置处理器主要用于识别获取 @Value 中配置的属性字符串
  2. @Value 属性值来源处理器 PropertySourcesPropertyResolver 的注册,该处理器负责从容器中取得指定的属性值
  3. 创建 Bean 对象时,容器使用以上两个组件对 @Value 标注的属性进行依赖注入

在这里插入图片描述

2. 源码分析

2.1 后置处理器 AutowiredAnnotationBeanPostProcessor 的注册

  1. 在 SpringBoot 注解 @Import 的原理-ConfigurationClassPostProcessor 源码解析 中,笔者分析了 SpringBoot 的基础注解 @Import 功能实现依赖的核心组件 ConfigurationClassPostProcessor 的注册,本文 @Value 依赖的组件 AutowiredAnnotationBeanPostProcessor 的注册流程与其基本一致,都是从 SpringApplication#prepareContext() 方法触发,一直调用到 AnnotationConfigUtils#registerAnnotationConfigProcessors() 方法

    AnnotationConfigUtils#registerAnnotationConfigProcessors() 负责解析注册比较重要的后置处理器,本文主要关注以下几个步骤:

    1. 新建 ContextAnnotationAutowireCandidateResolver 处理器,并通过beanFactory.setAutowireCandidateResolver() 调用 DefaultListableBeanFactory#setAutowireCandidateResolver() 方法将其缓存到容器内,后续将使用它来获取 @Value 注解中配置的字符串
    2. AutowiredAnnotationBeanPostProcessor 包装为 BeanDefinition 并注册,这个 Bean 后置处理器将用于处理 Bean 的内部属性依赖
    1. public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
    2. BeanDefinitionRegistry registry, @Nullable Object source) {
  1. DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
  2. if (beanFactory != null) {
  3. if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
  4. beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
  5. }
  6. if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
  7. beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
  8. }
  9. }
  10. Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
  11. if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
  12. RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
  13. def.setSource(source);
  14. beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
  15. }
  16. if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
  17. RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
  18. def.setSource(source);
  19. beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
  20. }
  21. // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
  22. if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
  23. RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
  24. def.setSource(source);
  25. beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
  26. }
  27. // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
  28. if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
  29. RootBeanDefinition def = new RootBeanDefinition();
  30. try {
  31. def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
  32. AnnotationConfigUtils.class.getClassLoader()));
  33. }
  34. catch (ClassNotFoundException ex) {
  35. throw new IllegalStateException(
  36. "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
  37. }
  38. def.setSource(source);
  39. beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
  40. }
  41. if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
  42. RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
  43. def.setSource(source);
  44. beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
  45. }
  46. if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
  47. RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
  48. def.setSource(source);
  49. beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
  50. }
  51. return beanDefs;
  52. }
  1. DefaultListableBeanFactory#setAutowireCandidateResolver() 方的处理很简单,可以看到就是一个赋值操作,将新建的 AutowireCandidateResolver 子类 ContextAnnotationAutowireCandidateResolver 对象保存在内部

    1. public void setAutowireCandidateResolver(final AutowireCandidateResolver autowireCandidateResolver) {
    2. Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
    3. if (autowireCandidateResolver instanceof BeanFactoryAware) {
    4. if (System.getSecurityManager() != null) {
    5. AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    6. ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(DefaultListableBeanFactory.this);
    7. return null;
    8. }, getAccessControlContext());
    9. }
    10. else {
    11. ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this);
    12. }
    13. }
    14. this.autowireCandidateResolver = autowireCandidateResolver;
    15. }

2.2 属性处理器 PropertySourcesPropertyResolver 的注册

  1. 在 SpringBoot 自动配置原理源码分析 中笔者分析了自动配置的实现原理,则可以知道自动配置类PropertyPlaceholderAutoConfiguration 中的 @Bean 标注的方法将被触发,用于创建对应的配置类对象 PropertySourcesPlaceholderConfigurer

    1. @Configuration(proxyBeanMethods = false)
    2. @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
    3. public class PropertyPlaceholderAutoConfiguration {
  1. @Bean
  2. @ConditionalOnMissingBean(search = SearchStrategy.CURRENT)
  3. public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
  4. return new PropertySourcesPlaceholderConfigurer();
  5. }
  6. }
  1. PropertySourcesPlaceholderConfigurer 实现了 BeanFactoryPostProcessor 接口,则当容器刷新时创建 Bean 工厂后会被用于对 Bean 工厂进行后置处理,触发 PropertySourcesPlaceholderConfigurer#postProcessBeanFactory() 方法,该方法比较重要的处理如下:

    1. 初始化属性来源列表 propertySources,可以看到此处会将 Environment 作为属性值来源
    2. 新建封装了属性来源列表 propertySourcesPropertySourcesPropertyResolver 对象,该对象主要负责从属性源中获取指定的属性值
    3. 调用 PropertySourcesPlaceholderConfigurer#processProperties() 方法将 PropertySourcesPropertyResolver 对象入参,进行下一步配置
    1. public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    2. if (this.propertySources == null) {
    3. this.propertySources = new MutablePropertySources();
    4. if (this.environment != null) {
    5. this.propertySources.addLast(
    6. new PropertySource<Environment>(ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME, this.environment) {
    7. @Override
    8. @Nullable
    9. public String getProperty(String key) {
    10. return this.source.getProperty(key);
    11. }
    12. }
    13. );
    14. }
    15. try {
    16. PropertySource<?> localPropertySource =
    17. new PropertiesPropertySource(LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME, mergeProperties());
    18. if (this.localOverride) {
    19. this.propertySources.addFirst(localPropertySource);
    20. }
    21. else {
    22. this.propertySources.addLast(localPropertySource);
    23. }
    24. }
    25. catch (IOException ex) {
    26. throw new BeanInitializationException("Could not load properties", ex);
    27. }
    28. }
    29. processProperties(beanFactory, new PropertySourcesPropertyResolver(this.propertySources));
    30. this.appliedPropertySources = this.propertySources;
    31. }
  2. PropertySourcesPlaceholderConfigurer#processProperties() 方法的重要处理如下:

    1. 通过 propertyResolver.setPlaceholderPrefix() 等方法调用,为 PropertySourcesPropertyResolver 对象设置属性解析的前后缀为 ${},分隔符为 :
    2. 使用 lambda 表达式 作为 StringValueResolver 的实现,随后调用父类 PlaceholderConfigurerSupport#doProcessProperties() 方法
    1. protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
    2. final ConfigurablePropertyResolver propertyResolver) throws BeansException {
  1. propertyResolver.setPlaceholderPrefix(this.placeholderPrefix);
  2. propertyResolver.setPlaceholderSuffix(this.placeholderSuffix);
  3. propertyResolver.setValueSeparator(this.valueSeparator);
  4. StringValueResolver valueResolver = strVal -> {
  5. String resolved = (this.ignoreUnresolvablePlaceholders ?
  6. propertyResolver.resolvePlaceholders(strVal) :
  7. propertyResolver.resolveRequiredPlaceholders(strVal));
  8. if (this.trimValues) {
  9. resolved = resolved.trim();
  10. }
  11. return (resolved.equals(this.nullValue) ? null : resolved);
  12. };
  13. doProcessProperties(beanFactoryToProcess, valueResolver);
  14. }
  1. PlaceholderConfigurerSupport#doProcessProperties() 方法中,本文主要关注beanFactoryToProcess.addEmbeddedValueResolver() 调用。这个处理实际调用到AbstractBeanFactory#addEmbeddedValueResolver() 方法,会将上一步骤构造的 lambda 表达式作为 StringValueResolver 的实例保存在 Bean 工厂内部

    1. protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
    2. StringValueResolver valueResolver) {
  1. BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
  2. String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
  3. for (String curName : beanNames) {
  4. // Check that we're not parsing our own bean definition,
  5. // to avoid failing on unresolvable placeholders in properties file locations.
  6. if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) {
  7. BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName);
  8. try {
  9. visitor.visitBeanDefinition(bd);
  10. }
  11. catch (Exception ex) {
  12. throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage(), ex);
  13. }
  14. }
  15. }
  16. // New in Spring 2.5: resolve placeholders in alias target names and aliases as well.
  17. beanFactoryToProcess.resolveAliases(valueResolver);
  18. // New in Spring 3.0: resolve placeholders in embedded values such as annotation attributes.
  19. beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
  20. }
  1. AbstractBeanFactory#addEmbeddedValueResolver() 方法的实现如下,可以看到只是个内部缓存动作,至此解析由 ${} 包裹的属性的属性处理器已经注册到容器内部

    1. @Override
    2. public void addEmbeddedValueResolver(StringValueResolver valueResolver) {
    3. Assert.notNull(valueResolver, "StringValueResolver must not be null");
    4. this.embeddedValueResolvers.add(valueResolver);
    5. }

2.3 @Value 标注字段的依赖处理

  1. 容器刷新过程中会触发创建 Bean 对象,这个流程必然调用到 DefaultListableBeanFactory#createBean() 方法,而这个方法由其父类方法AbstractAutowireCapableBeanFactory#createBean() 实现,可以看到以下调用中最终将触发执行 AbstractAutowireCapableBeanFactory#doCreateBean() 方法

    1. @Override
    2. @SuppressWarnings("unchecked")
    3. public <T> T createBean(Class<T> beanClass) throws BeansException {
    4. // Use prototype bean definition, to avoid registering bean as dependent bean.
    5. RootBeanDefinition bd = new RootBeanDefinition(beanClass);
    6. bd.setScope(SCOPE_PROTOTYPE);
    7. bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader());
    8. return (T) createBean(beanClass.getName(), bd, null);
    9. }
    10. @Override
    11. protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    12. throws BeanCreationException {
  1. if (logger.isTraceEnabled()) {
  2. logger.trace("Creating instance of bean '" + beanName + "'");
  3. }
  4. RootBeanDefinition mbdToUse = mbd;
  5. // Make sure bean class is actually resolved at this point, and
  6. // clone the bean definition in case of a dynamically resolved Class
  7. // which cannot be stored in the shared merged bean definition.
  8. Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
  9. if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
  10. mbdToUse = new RootBeanDefinition(mbd);
  11. mbdToUse.setBeanClass(resolvedClass);
  12. }
  13. // Prepare method overrides.
  14. try {
  15. mbdToUse.prepareMethodOverrides();
  16. }
  17. catch (BeanDefinitionValidationException ex) {
  18. throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
  19. beanName, "Validation of method overrides failed", ex);
  20. }
  21. try {
  22. // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
  23. Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
  24. if (bean != null) {
  25. return bean;
  26. }
  27. }
  28. catch (Throwable ex) {
  29. throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
  30. "BeanPostProcessor before instantiation of bean failed", ex);
  31. }
  32. try {
  33. Object beanInstance = doCreateBean(beanName, mbdToUse, args);
  34. if (logger.isTraceEnabled()) {
  35. logger.trace("Finished creating instance of bean '" + beanName + "'");
  36. }
  37. return beanInstance;
  38. }
  39. catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
  40. // A previously detected exception with proper bean creation context already,
  41. // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
  42. throw ex;
  43. }
  44. catch (Throwable ex) {
  45. throw new BeanCreationException(
  46. mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
  47. }
  48. }
  1. AbstractAutowireCapableBeanFactory#doCreateBean() 方法比较长,核心为以下两步:

    1. 调用 AbstractAutowireCapableBeanFactory#createBeanInstance() 方法创建属性空白的 Bean 实例
    2. 调用 AbstractAutowireCapableBeanFactory#populateBean() 方法为 Bean 实例填充属性
    1. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
    2. throws BeanCreationException {
  1. // Instantiate the bean.
  2. BeanWrapper instanceWrapper = null;
  3. if (mbd.isSingleton()) {
  4. instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  5. }
  6. if (instanceWrapper == null) {
  7. instanceWrapper = createBeanInstance(beanName, mbd, args);
  8. }
  9. final Object bean = instanceWrapper.getWrappedInstance();
  10. Class<?> beanType = instanceWrapper.getWrappedClass();
  11. if (beanType != NullBean.class) {
  12. mbd.resolvedTargetType = beanType;
  13. }
  14. // Allow post-processors to modify the merged bean definition.
  15. synchronized (mbd.postProcessingLock) {
  16. if (!mbd.postProcessed) {
  17. try {
  18. applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
  19. }
  20. catch (Throwable ex) {
  21. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
  22. "Post-processing of merged bean definition failed", ex);
  23. }
  24. mbd.postProcessed = true;
  25. }
  26. }
  27. // Eagerly cache singletons to be able to resolve circular references
  28. // even when triggered by lifecycle interfaces like BeanFactoryAware.
  29. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
  30. isSingletonCurrentlyInCreation(beanName));
  31. if (earlySingletonExposure) {
  32. if (logger.isTraceEnabled()) {
  33. logger.trace("Eagerly caching bean '" + beanName +
  34. "' to allow for resolving potential circular references");
  35. }
  36. addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
  37. }
  38. // Initialize the bean instance.
  39. Object exposedObject = bean;
  40. try {
  41. populateBean(beanName, mbd, instanceWrapper);
  42. exposedObject = initializeBean(beanName, exposedObject, mbd);
  43. }
  44. catch (Throwable ex) {
  45. if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
  46. throw (BeanCreationException) ex;
  47. }
  48. else {
  49. throw new BeanCreationException(
  50. mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
  51. }
  52. }
  53. if (earlySingletonExposure) {
  54. Object earlySingletonReference = getSingleton(beanName, false);
  55. if (earlySingletonReference != null) {
  56. if (exposedObject == bean) {
  57. exposedObject = earlySingletonReference;
  58. }
  59. else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
  60. String[] dependentBeans = getDependentBeans(beanName);
  61. Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
  62. for (String dependentBean : dependentBeans) {
  63. if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
  64. actualDependentBeans.add(dependentBean);
  65. }
  66. }
  67. if (!actualDependentBeans.isEmpty()) {
  68. throw new BeanCurrentlyInCreationException(beanName,
  69. "Bean with name '" + beanName + "' has been injected into other beans [" +
  70. StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
  71. "] in its raw version as part of a circular reference, but has eventually been " +
  72. "wrapped. This means that said other beans do not use the final version of the " +
  73. "bean. This is often the result of over-eager type matching - consider using " +
  74. "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
  75. }
  76. }
  77. }
  78. }
  79. // Register bean as disposable.
  80. try {
  81. registerDisposableBeanIfNecessary(beanName, bean, mbd);
  82. }
  83. catch (BeanDefinitionValidationException ex) {
  84. throw new BeanCreationException(
  85. mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
  86. }
  87. return exposedObject;
  88. }
  1. AbstractAutowireCapableBeanFactory#populateBean() 方法内容比较多,本文重点关注其使用 InstantiationAwareBeanPostProcessor 后置处理器处理 Bean 属性的逻辑

    1. protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    2. if (bw == null) {
    3. if (mbd.hasPropertyValues()) {
    4. throw new BeanCreationException(
    5. mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
    6. }
    7. else {
    8. // Skip property population phase for null instance.
    9. return;
    10. }
    11. }
    12. // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    13. // state of the bean before properties are set. This can be used, for example,
    14. // to support styles of field injection.
    15. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    16. for (BeanPostProcessor bp : getBeanPostProcessors()) {
    17. if (bp instanceof InstantiationAwareBeanPostProcessor) {
    18. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    19. if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    20. return;
    21. }
    22. }
    23. }
    24. }
    25. PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    26. int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    27. if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    28. MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    29. // Add property values based on autowire by name if applicable.
    30. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
    31. autowireByName(beanName, mbd, bw, newPvs);
    32. }
    33. // Add property values based on autowire by type if applicable.
    34. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    35. autowireByType(beanName, mbd, bw, newPvs);
    36. }
    37. pvs = newPvs;
    38. }
    39. boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    40. boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
    41. PropertyDescriptor[] filteredPds = null;
    42. if (hasInstAwareBpps) {
    43. if (pvs == null) {
    44. pvs = mbd.getPropertyValues();
    45. }
    46. for (BeanPostProcessor bp : getBeanPostProcessors()) {
    47. if (bp instanceof InstantiationAwareBeanPostProcessor) {
    48. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    49. PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
    50. if (pvsToUse == null) {
    51. if (filteredPds == null) {
    52. filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    53. }
    54. pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
    55. if (pvsToUse == null) {
    56. return;
    57. }
    58. }
    59. pvs = pvsToUse;
    60. }
    61. }
    62. }
    63. if (needsDepCheck) {
    64. if (filteredPds == null) {
    65. filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    66. }
    67. checkDependencies(beanName, mbd, filteredPds, pvs);
    68. }
    69. if (pvs != null) {
    70. applyPropertyValues(beanName, mbd, bw, pvs);
    71. }
    72. }
  2. 在2.1节中注册的 AutowiredAnnotationBeanPostProcessor 就实现了 InstantiationAwareBeanPostProcessor 接口,则此处 AutowiredAnnotationBeanPostProcessor#postProcessProperties() 将被触发调用,可以看到此处的关键处理有两步:

    1. 调用 AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata() 方法创建注入元数据对象 InjectionMetadata
    2. 调用 InjectionMetadata#inject() 方法进行数据注入
    1. public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    2. InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    3. try {
    4. metadata.inject(bean, beanName, pvs);
    5. }
    6. catch (BeanCreationException ex) {
    7. throw ex;
    8. }
    9. catch (Throwable ex) {
    10. throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    11. }
    12. return pvs;
    13. }
  3. AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata() 的处理是,先从缓存中获取 InjectionMetadata 对象,获取不到则调用 AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata() 构建

    1. private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
    2. // Fall back to class name as cache key, for backwards compatibility with custom callers.
    3. String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
    4. // Quick check on the concurrent map first, with minimal locking.
    5. InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
    6. if (InjectionMetadata.needsRefresh(metadata, clazz)) {
    7. synchronized (this.injectionMetadataCache) {
    8. metadata = this.injectionMetadataCache.get(cacheKey);
    9. if (InjectionMetadata.needsRefresh(metadata, clazz)) {
    10. if (metadata != null) {
    11. metadata.clear(pvs);
    12. }
    13. metadata = buildAutowiringMetadata(clazz);
    14. this.injectionMetadataCache.put(cacheKey, metadata);
    15. }
    16. }
    17. }
    18. return metadata;
    19. }
  4. AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata() 方法实现如下,可以看到这里会将目标类定义的字段 Field方法 Method 分别处理。具体逻辑是通过 AutowiredAnnotationBeanPostProcessor#findAutowiredAnnotation() 方法获取字段或者方法上标注的特定注解,如果能获取到说明需要处理依赖注入,则生成对应的 InjectedElement 实例,代表一个需要处理注入的元素

    1. private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    2. if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
    3. return InjectionMetadata.EMPTY;
    4. }
    5. List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    6. Class<?> targetClass = clazz;
    7. do {
    8. final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
    9. ReflectionUtils.doWithLocalFields(targetClass, field -> {
    10. MergedAnnotation<?> ann = findAutowiredAnnotation(field);
    11. if (ann != null) {
    12. if (Modifier.isStatic(field.getModifiers())) {
    13. if (logger.isInfoEnabled()) {
    14. logger.info("Autowired annotation is not supported on static fields: " + field);
    15. }
    16. return;
    17. }
    18. boolean required = determineRequiredStatus(ann);
    19. currElements.add(new AutowiredFieldElement(field, required));
    20. }
    21. });
    22. ReflectionUtils.doWithLocalMethods(targetClass, method -> {
    23. Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
    24. if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
    25. return;
    26. }
    27. MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
    28. if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
    29. if (Modifier.isStatic(method.getModifiers())) {
    30. if (logger.isInfoEnabled()) {
    31. logger.info("Autowired annotation is not supported on static methods: " + method);
    32. }
    33. return;
    34. }
    35. if (method.getParameterCount() == 0) {
    36. if (logger.isInfoEnabled()) {
    37. logger.info("Autowired annotation should only be used on methods with parameters: " +
    38. method);
    39. }
    40. }
    41. boolean required = determineRequiredStatus(ann);
    42. PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
    43. currElements.add(new AutowiredMethodElement(method, required, pd));
    44. }
    45. });
    46. elements.addAll(0, currElements);
    47. targetClass = targetClass.getSuperclass();
    48. }
    49. while (targetClass != null && targetClass != Object.class);
    50. return InjectionMetadata.forElements(elements, clazz);
    51. }
  5. AutowiredAnnotationBeanPostProcessor#findAutowiredAnnotation() 方法其实就是查看字段或者方法上是否存在指定的三个注解 @Autowired、@Value、@Inject

    1. @Nullable
    2. private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
    3. MergedAnnotations annotations = MergedAnnotations.from(ao);
    4. for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
    5. MergedAnnotation<?> annotation = annotations.get(type);
    6. if (annotation.isPresent()) {
    7. return annotation;
    8. }
    9. }
    10. return null;
    11. }
  6. 经过以上步骤,Bean 对象需要处理依赖注入的元素都封装在了 InjectionMetadata 对象中,回到步骤4第2步, InjectionMetadata#inject() 方法遍历其内部待填充属性的元素,调用其InjectedElement#inject()进行属性注入

    1. public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    2. Collection<InjectedElement> checkedElements = this.checkedElements;
    3. Collection<InjectedElement> elementsToIterate =
    4. (checkedElements != null ? checkedElements : this.injectedElements);
    5. if (!elementsToIterate.isEmpty()) {
    6. for (InjectedElement element : elementsToIterate) {
    7. if (logger.isTraceEnabled()) {
    8. logger.trace("Processing injected element of bean '" + beanName + "': " + element);
    9. }
    10. element.inject(target, beanName, pvs);
    11. }
    12. }
    13. }
  7. 本文以字段属性注入为例,AutowiredFieldElement#inject() 方法的实现如下,核心逻辑可分为两步:

    1. 调用 DefaultListableBeanFactory#resolveDependency() 从容器中获取字段的属性值
    2. field.set() 反射调用字段赋值方法,完成属性值的注入
    1. @Override
    2. protected void inject(Object bean, @Nullable String beanName, @Nullable 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<>(1);
    12. Assert.state(beanFactory != null, "No BeanFactory available");
    13. TypeConverter typeConverter = beanFactory.getTypeConverter();
    14. try {
    15. value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
    16. }
    17. catch (BeansException ex) {
    18. throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
    19. }
    20. synchronized (this) {
    21. if (!this.cached) {
    22. if (value != null || this.required) {
    23. this.cachedFieldValue = desc;
    24. registerDependentBeans(beanName, autowiredBeanNames);
    25. if (autowiredBeanNames.size() == 1) {
    26. String autowiredBeanName = autowiredBeanNames.iterator().next();
    27. if (beanFactory.containsBean(autowiredBeanName) &&
    28. beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
    29. this.cachedFieldValue = new ShortcutDependencyDescriptor(
    30. desc, autowiredBeanName, field.getType());
    31. }
    32. }
    33. }
    34. else {
    35. this.cachedFieldValue = null;
    36. }
    37. this.cached = true;
    38. }
    39. }
    40. }
    41. if (value != null) {
    42. ReflectionUtils.makeAccessible(field);
    43. field.set(bean, value);
    44. }
    45. }
  8. DefaultListableBeanFactory#resolveDependency() 会做常规的判断,核心是调用DefaultListableBeanFactory#doResolveDependency() 方法

    1. public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
    2. @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
  1. descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
  2. if (Optional.class == descriptor.getDependencyType()) {
  3. return createOptionalDependency(descriptor, requestingBeanName);
  4. }
  5. else if (ObjectFactory.class == descriptor.getDependencyType() ||
  6. ObjectProvider.class == descriptor.getDependencyType()) {
  7. return new DependencyObjectProvider(descriptor, requestingBeanName);
  8. }
  9. else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
  10. return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
  11. }
  12. else {
  13. Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
  14. descriptor, requestingBeanName);
  15. if (result == null) {
  16. result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
  17. }
  18. return result;
  19. }
  20. }
  1. DefaultListableBeanFactory#doResolveDependency() 方法重要流程分为以下几步:

    1. getAutowireCandidateResolver().getSuggestedValue(descriptor) 调用 2.1节提到的解析器 ContextAnnotationAutowireCandidateResolver#getSuggestedValue() 方法,将元素的注解中配置的字符串取出来。例如字段上标注了@Value("#{'${spring.data.users:nathan}'.split(',')}"),则这个步骤将取得字符串 #{'${spring.data.users:nathan}'.split(',')}
    2. 调用父类 AbstractBeanFactory#resolveEmbeddedValue() 方法解析字符串#{'${spring.data.users:nathan}'.split(',')}${} 包裹的部分,具体逻辑为使用键 spring.data.users 去容器中获取属性值,获取不到则使用冒号: 后默认的 nathan 作为值,方法返回后取得字符串 #{'nathan'.split(',')}
    3. 调用父类 AbstractBeanFactory#evaluateBeanDefinitionString() 方法使用 SpEL 表达式 解析字符串 #{'nathan'.split(',')},本例中实际是个字符串分割的操作,方法返回后获得一个字符串数组对象 [“nathan”]
    4. 调用类型转换器 TypeConverter#convertIfNecessary() 方法将以上步骤处理取得的值转换为目标字段的类型并返回
    1. @Nullable
    2. public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
    3. @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
  1. InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
  2. try {
  3. Object shortcut = descriptor.resolveShortcut(this);
  4. if (shortcut != null) {
  5. return shortcut;
  6. }
  7. Class<?> type = descriptor.getDependencyType();
  8. Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
  9. if (value != null) {
  10. if (value instanceof String) {
  11. String strVal = resolveEmbeddedValue((String) value);
  12. BeanDefinition bd = (beanName != null && containsBean(beanName) ?
  13. getMergedBeanDefinition(beanName) : null);
  14. value = evaluateBeanDefinitionString(strVal, bd);
  15. }
  16. TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
  17. try {
  18. return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
  19. }
  20. catch (UnsupportedOperationException ex) {
  21. // A custom TypeConverter which does not support TypeDescriptor resolution...
  22. return (descriptor.getField() != null ?
  23. converter.convertIfNecessary(value, type, descriptor.getField()) :
  24. converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
  25. }
  26. }
  27. Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
  28. if (multipleBeans != null) {
  29. return multipleBeans;
  30. }
  31. Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
  32. if (matchingBeans.isEmpty()) {
  33. if (isRequired(descriptor)) {
  34. raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
  35. }
  36. return null;
  37. }
  38. String autowiredBeanName;
  39. Object instanceCandidate;
  40. if (matchingBeans.size() > 1) {
  41. autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
  42. if (autowiredBeanName == null) {
  43. if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
  44. return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
  45. }
  46. else {
  47. // In case of an optional Collection/Map, silently ignore a non-unique case:
  48. // possibly it was meant to be an empty collection of multiple regular beans
  49. // (before 4.3 in particular when we didn't even look for collection beans).
  50. return null;
  51. }
  52. }
  53. instanceCandidate = matchingBeans.get(autowiredBeanName);
  54. }
  55. else {
  56. // We have exactly one match.
  57. Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
  58. autowiredBeanName = entry.getKey();
  59. instanceCandidate = entry.getValue();
  60. }
  61. if (autowiredBeanNames != null) {
  62. autowiredBeanNames.add(autowiredBeanName);
  63. }
  64. if (instanceCandidate instanceof Class) {
  65. instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
  66. }
  67. Object result = instanceCandidate;
  68. if (result instanceof NullBean) {
  69. if (isRequired(descriptor)) {
  70. raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
  71. }
  72. result = null;
  73. }
  74. if (!ClassUtils.isAssignableValue(type, result)) {
  75. throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
  76. }
  77. return result;
  78. }
  79. finally {
  80. ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
  81. }
  82. }
  1. AbstractBeanFactory#resolveEmbeddedValue() 方法比较简单,就是遍历内部缓存的 StringValueResolver 列表,去获取目标属性值。在 2.2节步骤5 中,我们已经注册一个 lambda 表达式 作为 StringValueResolver 在容器内部,则此处会触发PropertySourcesPlaceholderConfigurer#processProperties() 中构造的表达式执行

    1. public String resolveEmbeddedValue(@Nullable String value) {
    2. if (value == null) {
    3. return null;
    4. }
    5. String result = value;
    6. for (StringValueResolver resolver : this.embeddedValueResolvers) {
    7. result = resolver.resolveStringValue(result);
    8. if (result == null) {
    9. return null;
    10. }
    11. }
    12. return result;
    13. }
  2. PropertySourcesPlaceholderConfigurer#processProperties() 中构造的表达式如下,可以看到此处最终使用目标键获取属性的操作是在调用的 PropertySourcesPropertyResolver#resolveRequiredPlaceholders() 方法中

    1. protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
    2. final ConfigurablePropertyResolver propertyResolver) throws BeansException {
  1. propertyResolver.setPlaceholderPrefix(this.placeholderPrefix);
  2. propertyResolver.setPlaceholderSuffix(this.placeholderSuffix);
  3. propertyResolver.setValueSeparator(this.valueSeparator);
  4. StringValueResolver valueResolver = strVal -> {
  5. String resolved = (this.ignoreUnresolvablePlaceholders ?
  6. propertyResolver.resolvePlaceholders(strVal) :
  7. propertyResolver.resolveRequiredPlaceholders(strVal));
  8. if (this.trimValues) {
  9. resolved = resolved.trim();
  10. }
  11. return (resolved.equals(this.nullValue) ? null : resolved);
  12. };
  13. ......
  14. }
  1. PropertySourcesPropertyResolver#resolveRequiredPlaceholders() 由其父类 AbstractPropertyResolver#resolveRequiredPlaceholders()实现,主要流程分为两步:

    1. 调用 AbstractPropertyResolver#createPlaceholderHelper() 方法创建 PropertyPlaceholderHelper对象
    2. 调用 AbstractPropertyResolver#doResolvePlaceholders() 方法,进而调用 PropertyPlaceholderHelper#replacePlaceholders() 方法获取属性值,处理原字符串替换
    1. public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
    2. if (this.strictHelper == null) {
    3. this.strictHelper = createPlaceholderHelper(false);
    4. }
    5. return doResolvePlaceholders(text, this.strictHelper);
    6. }
    7. private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
    8. return helper.replacePlaceholders(text, this::getPropertyAsRawString);
    9. }
  2. PropertyPlaceholderHelper#replacePlaceholders() 方法只是个入口,核心在 PropertyPlaceholderHelper#parseStringValue() 方法的实现,重要逻辑如下:

    1. 递归查找目标字符串中 ${} 包裹的字符串,直到最里层
    2. 使用分隔符 : 切割 ${} 包裹的字符串,将其前半部分作为入参调用 PlaceholderResolver#resolvePlaceholder() 方法取容器中的目标属性值(没有取到则将分隔符 : 后面的字符串作为目标值),替换掉原字符串部分
    3. 递归收束,最终返回给调用方的即为替换掉了 ${} 包裹内容的字符串
    1. public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) {
    2. Assert.notNull(value, "'value' must not be null");
    3. return parseStringValue(value, placeholderResolver, null);
    4. }
    5. protected String parseStringValue(
    6. String value, PlaceholderResolver placeholderResolver, @Nullable Set<String> visitedPlaceholders) {
  1. int startIndex = value.indexOf(this.placeholderPrefix);
  2. if (startIndex == -1) {
  3. return value;
  4. }
  5. StringBuilder result = new StringBuilder(value);
  6. while (startIndex != -1) {
  7. int endIndex = findPlaceholderEndIndex(result, startIndex);
  8. if (endIndex != -1) {
  9. String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
  10. String originalPlaceholder = placeholder;
  11. if (visitedPlaceholders == null) {
  12. visitedPlaceholders = new HashSet<>(4);
  13. }
  14. if (!visitedPlaceholders.add(originalPlaceholder)) {
  15. throw new IllegalArgumentException(
  16. "Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
  17. }
  18. // Recursive invocation, parsing placeholders contained in the placeholder key.
  19. placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
  20. // Now obtain the value for the fully resolved key...
  21. String propVal = placeholderResolver.resolvePlaceholder(placeholder);
  22. if (propVal == null && this.valueSeparator != null) {
  23. int separatorIndex = placeholder.indexOf(this.valueSeparator);
  24. if (separatorIndex != -1) {
  25. String actualPlaceholder = placeholder.substring(0, separatorIndex);
  26. String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
  27. propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
  28. if (propVal == null) {
  29. propVal = defaultValue;
  30. }
  31. }
  32. }
  33. if (propVal != null) {
  34. // Recursive invocation, parsing placeholders contained in the
  35. // previously resolved placeholder value.
  36. propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
  37. result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
  38. if (logger.isTraceEnabled()) {
  39. logger.trace("Resolved placeholder '" + placeholder + "'");
  40. }
  41. startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());
  42. }
  43. else if (this.ignoreUnresolvablePlaceholders) {
  44. // Proceed with unprocessed value.
  45. startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
  46. }
  47. else {
  48. throw new IllegalArgumentException("Could not resolve placeholder '" +
  49. placeholder + "'" + " in value \"" + value + "\"");
  50. }
  51. visitedPlaceholders.remove(originalPlaceholder);
  52. }
  53. else {
  54. startIndex = -1;
  55. }
  56. }
  57. return result.toString();
  58. }
  1. 回到步骤11第3步,SpEL 表达式的解析入口为 AbstractBeanFactory#evaluateBeanDefinitionString() 方法,此处使用了 Spring 中 SpEL 表达式模块的相关 API, 本文不做进一步分析,有兴趣的读者可以自行搜索学习

    1. protected Object evaluateBeanDefinitionString(@Nullable String value, @Nullable BeanDefinition beanDefinition) {
    2. if (this.beanExpressionResolver == null) {
    3. return value;
    4. }
    5. Scope scope = null;
    6. if (beanDefinition != null) {
    7. String scopeName = beanDefinition.getScope();
    8. if (scopeName != null) {
    9. scope = getRegisteredScope(scopeName);
    10. }
    11. }
    12. return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
    13. }
  2. 回到步骤11第4步,经过类型转换器将处理得到的属性值转换为目标字段的类型后,方法栈再回到步骤9第2步,一次属性注入的流程基本结束。类型转换的部分本文不再分析,读者有兴趣可以自行深入,至此 @Value 实现原理的分析暂告段落

发表评论

表情:
评论列表 (有 0 条评论,87人围观)

还没有评论,来说两句吧...

相关阅读