- 前言
- 1. @Value 的源码处理流程
- 2. 源码分析
- 2.1 后置处理器 AutowiredAnnotationBeanPostProcessor 的注册
- 2.2 属性处理器 PropertySourcesPropertyResolver 的注册
- 2.3 @Value 标注字段的依赖处理
SpringBoot 提供了很多开箱即用的实用工具,比如我们可以使用 @Value 注解获取容器中的配置数据,自动完成属性的赋值,本文即从源码角度来解析 @Value 的实现机制
1. @Value 的源码处理流程@Value 实现属性注入的源码流程如下图所示,笔者将其从组件的准备到组件的使用分为了三个部分:
2. 源码分析 2.1 后置处理器 AutowiredAnnotationBeanPostProcessor 的注册
- @Value 后置处理器 AutowiredAnnotationBeanPostProcessor 的注册,这个后置处理器主要用于识别获取 @Value 中配置的属性字符串
- @Value 属性值来源处理器 PropertySourcesPropertyResolver 的注册,该处理器负责从容器中取得指定的属性值
- 创建 Bean 对象时,容器使用以上两个组件对 @Value 标注的属性进行依赖注入
-
在 SpringBoot 注解 @import 的原理-ConfigurationClassPostProcessor 源码解析 中,笔者分析了 SpringBoot 的基础注解 @import 功能实现依赖的核心组件 ConfigurationClassPostProcessor 的注册,本文 @Value 依赖的组件 AutowiredAnnotationBeanPostProcessor 的注册流程与其基本一致,都是从 SpringApplication#prepareContext() 方法触发,一直调用到 AnnotationConfigUtils#registerAnnotationConfigProcessors() 方法
AnnotationConfigUtils#registerAnnotationConfigProcessors() 负责解析注册比较重要的后置处理器,本文主要关注以下几个步骤:
- 新建 ContextAnnotationAutowireCandidateResolver 处理器,并通过beanFactory.setAutowireCandidateResolver() 调用 DefaultListableBeanFactory#setAutowireCandidateResolver() 方法将其缓存到容器内,后续将使用它来获取 @Value 注解中配置的字符串
- 将 AutowiredAnnotationBeanPostProcessor 包装为 BeanDefinition 并注册,这个 Bean 后置处理器将用于处理 Bean 的内部属性依赖
public static Set
registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, @Nullable Object source) { DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry); if (beanFactory != null) { if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) { beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE); } if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) { beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); } } Set beanDefs = new linkedHashSet<>(8); if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor. if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)); } // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor. if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(); try { def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, AnnotationConfigUtils.class.getClassLoader())); } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex); } def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME)); } return beanDefs; } -
DefaultListableBeanFactory#setAutowireCandidateResolver() 方的处理很简单,可以看到就是一个赋值操作,将新建的 AutowireCandidateResolver 子类 ContextAnnotationAutowireCandidateResolver 对象保存在内部
public void setAutowireCandidateResolver(final AutowireCandidateResolver autowireCandidateResolver) { Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null"); if (autowireCandidateResolver instanceof BeanFactoryAware) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction
-
在 SpringBoot 自动配置原理源码分析 中笔者分析了自动配置的实现原理,则可以知道自动配置类PropertyPlaceholderAutoConfiguration 中的 @Bean 标注的方法将被触发,用于创建对应的配置类对象 PropertySourcesPlaceholderConfigurer
@Configuration(proxyBeanMethods = false) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) public class PropertyPlaceholderAutoConfiguration { @Bean @ConditionalOnMissingBean(search = SearchStrategy.CURRENT) public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); } } -
PropertySourcesPlaceholderConfigurer 实现了 BeanFactoryPostProcessor 接口,则当容器刷新时创建 Bean 工厂后会被用于对 Bean 工厂进行后置处理,触发 PropertySourcesPlaceholderConfigurer#postProcessBeanFactory() 方法,该方法比较重要的处理如下:
- 初始化属性来源列表 propertySources,可以看到此处会将 Environment 作为属性值来源
- 新建封装了属性来源列表 propertySources 的 PropertySourcesPropertyResolver 对象,该对象主要负责从属性源中获取指定的属性值
- 调用 PropertySourcesPlaceholderConfigurer#processProperties() 方法将 PropertySourcesPropertyResolver 对象入参,进行下一步配置
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { if (this.propertySources == null) { this.propertySources = new MutablePropertySources(); if (this.environment != null) { this.propertySources.addLast( new PropertySource(ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME, this.environment) { @Override @Nullable public String getProperty(String key) { return this.source.getProperty(key); } } ); } try { PropertySource> localPropertySource = new PropertiesPropertySource(LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME, mergeProperties()); if (this.localOverride) { this.propertySources.addFirst(localPropertySource); } else { this.propertySources.addLast(localPropertySource); } } catch (IOException ex) { throw new BeanInitializationException("Could not load properties", ex); } } processProperties(beanFactory, new PropertySourcesPropertyResolver(this.propertySources)); this.appliedPropertySources = this.propertySources; } -
PropertySourcesPlaceholderConfigurer#processProperties() 方法的重要处理如下:
- 通过 propertyResolver.setPlaceholderPrefix() 等方法调用,为 PropertySourcesPropertyResolver 对象设置属性解析的前后缀为 ${},分隔符为 :
- 使用 lambda 表达式 作为 StringValueResolver 的实现,随后调用父类 PlaceholderConfigurerSupport#doProcessProperties() 方法
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, final ConfigurablePropertyResolver propertyResolver) throws BeansException { propertyResolver.setPlaceholderPrefix(this.placeholderPrefix); propertyResolver.setPlaceholderSuffix(this.placeholderSuffix); propertyResolver.setValueSeparator(this.valueSeparator); StringValueResolver valueResolver = strVal -> { String resolved = (this.ignoreUnresolvablePlaceholders ? propertyResolver.resolvePlaceholders(strVal) : propertyResolver.resolveRequiredPlaceholders(strVal)); if (this.trimValues) { resolved = resolved.trim(); } return (resolved.equals(this.nullValue) ? null : resolved); }; doProcessProperties(beanFactoryToProcess, valueResolver); } -
PlaceholderConfigurerSupport#doProcessProperties() 方法中,本文主要关注beanFactoryToProcess.addEmbeddedValueResolver() 调用。这个处理实际调用到AbstractBeanFactory#addEmbeddedValueResolver() 方法,会将上一步骤构造的 lambda 表达式作为 StringValueResolver 的实例保存在 Bean 工厂内部
protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess, StringValueResolver valueResolver) { BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver); String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames(); for (String curName : beanNames) { // Check that we're not parsing our own bean definition, // to avoid failing on unresolvable placeholders in properties file locations. if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) { BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName); try { visitor.visitBeanDefinition(bd); } catch (Exception ex) { throw new BeanDefinitionStoreException(bd.getResourceDescription(), curName, ex.getMessage(), ex); } } } // New in Spring 2.5: resolve placeholders in alias target names and aliases as well. beanFactoryToProcess.resolveAliases(valueResolver); // New in Spring 3.0: resolve placeholders in embedded values such as annotation attributes. beanFactoryToProcess.addEmbeddedValueResolver(valueResolver); } -
AbstractBeanFactory#addEmbeddedValueResolver() 方法的实现如下,可以看到只是个内部缓存动作,至此解析由 ${} 包裹的属性的属性处理器已经注册到容器内部
@Override public void addEmbeddedValueResolver(StringValueResolver valueResolver) { Assert.notNull(valueResolver, "StringValueResolver must not be null"); this.embeddedValueResolvers.add(valueResolver); }
-
容器刷新过程中会触发创建 Bean 对象,这个流程必然调用到 DefaultListableBeanFactory#createBean() 方法,而这个方法由其父类方法AbstractAutowireCapableBeanFactory#createBean() 实现,可以看到以下调用中最终将触发执行 AbstractAutowireCapableBeanFactory#doCreateBean() 方法
@Override @SuppressWarnings("unchecked") publicT createBean(Class 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); } @Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isTraceEnabled()) { logger.trace("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. Class> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } 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) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } } -
AbstractAutowireCapableBeanFactory#doCreateBean() 方法比较长,核心为以下两步:
- 调用 AbstractAutowireCapableBeanFactory#createBeanInstance() 方法创建属性空白的 Bean 实例
- 调用 AbstractAutowireCapableBeanFactory#populateBean() 方法为 Bean 实例填充属性
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = instanceWrapper.getWrappedInstance(); Class> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // 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; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); SetactualDependentBeans = new linkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); } } } } // Register bean as disposable. try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; } -
AbstractAutowireCapableBeanFactory#populateBean() 方法内容比较多,本文重点关注其使用 InstantiationAwareBeanPostProcessor 后置处理器处理 Bean 属性的逻辑
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { if (mbd.hasPropertyValues()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } 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; } } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } } -
在2.1节中注册的 AutowiredAnnotationBeanPostProcessor 就实现了 InstantiationAwareBeanPostProcessor 接口,则此处 AutowiredAnnotationBeanPostProcessor#postProcessProperties() 将被触发调用,可以看到此处的关键处理有两步:
- 调用 AutowiredAnnotationBeanPostProcessor#findAutowiringmetadata() 方法创建注入元数据对象 Injectionmetadata
- 调用 Injectionmetadata#inject() 方法进行数据注入
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; } -
AutowiredAnnotationBeanPostProcessor#findAutowiringmetadata() 的处理是,先从缓存中获取 Injectionmetadata 对象,获取不到则调用 AutowiredAnnotationBeanPostProcessor#buildAutowiringmetadata() 构建
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; } -
AutowiredAnnotationBeanPostProcessor#buildAutowiringmetadata() 方法实现如下,可以看到这里会将目标类定义的字段 Field 和 方法 Method 分别处理。具体逻辑是通过 AutowiredAnnotationBeanPostProcessor#findAutowiredAnnotation() 方法获取字段或者方法上标注的特定注解,如果能获取到说明需要处理依赖注入,则生成对应的 InjectedElement 实例,代表一个需要处理注入的元素
private Injectionmetadata buildAutowiringmetadata(final Class> clazz) { if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) { return Injectionmetadata.EMPTY; } Listelements = new ArrayList<>(); Class> targetClass = clazz; do { final List 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#findAutowiredAnnotation() 方法其实就是查看字段或者方法上是否存在指定的三个注解 @Autowired、@Value、@Inject
@Nullable private MergedAnnotation> findAutowiredAnnotation(AccessibleObject ao) { MergedAnnotations annotations = MergedAnnotations.from(ao); for (Class extends Annotation> type : this.autowiredAnnotationTypes) { MergedAnnotation> annotation = annotations.get(type); if (annotation.isPresent()) { return annotation; } } return null; } -
经过以上步骤,Bean 对象需要处理依赖注入的元素都封装在了 Injectionmetadata 对象中,回到步骤4第2步, Injectionmetadata#inject() 方法遍历其内部待填充属性的元素,调用其InjectedElement#inject()进行属性注入
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { CollectioncheckedElements = this.checkedElements; Collection elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements); if (!elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { if (logger.isTraceEnabled()) { logger.trace("Processing injected element of bean '" + beanName + "': " + element); } element.inject(target, beanName, pvs); } } } -
本文以字段属性注入为例,AutowiredFieldElement#inject() 方法的实现如下,核心逻辑可分为两步:
- 调用 DefaultListableBeanFactory#resolveDependency() 从容器中获取字段的属性值
- field.set() 反射调用字段赋值方法,完成属性值的注入
@Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Field field = (Field) this.member; Object value; if (this.cached) { value = resolvedCachedArgument(beanName, this.cachedFieldValue); } else { DependencyDescriptor desc = new DependencyDescriptor(field, this.required); desc.setContainingClass(bean.getClass()); SetautowiredBeanNames = new linkedHashSet<>(1); Assert.state(beanFactory != null, "No BeanFactory available"); TypeConverter typeConverter = beanFactory.getTypeConverter(); try { value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } synchronized (this) { if (!this.cached) { if (value != null || this.required) { this.cachedFieldValue = desc; registerDependentBeans(beanName, autowiredBeanNames); if (autowiredBeanNames.size() == 1) { String autowiredBeanName = autowiredBeanNames.iterator().next(); if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { this.cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } else { this.cachedFieldValue = null; } this.cached = true; } } } if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value); } } -
DefaultListableBeanFactory#resolveDependency() 会做常规的判断,核心是调用DefaultListableBeanFactory#doResolveDependency() 方法
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set
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; } } -
DefaultListableBeanFactory#doResolveDependency() 方法重要流程分为以下几步:
- getAutowireCandidateResolver().getSuggestedValue(descriptor) 调用 2.1节提到的解析器 ContextAnnotationAutowireCandidateResolver#getSuggestedValue() 方法,将元素的注解中配置的字符串取出来。例如字段上标注了@Value("#{'${spring.data.users:nathan}'.split(',')}"),则这个步骤将取得字符串 #{'${spring.data.users:nathan}'.split(',')}
- 调用父类 AbstractBeanFactory#resolveEmbeddedValue() 方法解析字符串#{'${spring.data.users:nathan}'.split(',')} 中 ${} 包裹的部分,具体逻辑为使用键 spring.data.users 去容器中获取属性值,获取不到则使用冒号: 后默认的 nathan 作为值,方法返回后取得字符串 #{'nathan'.split(',')}
- 调用父类 AbstractBeanFactory#evaluateBeanDefinitionString() 方法使用 SpEL 表达式 解析字符串 #{'nathan'.split(',')},本例中实际是个字符串分割的操作,方法返回后获得一个字符串数组对象 [“nathan”]
- 调用类型转换器 TypeConverter#convertIfNecessary() 方法将以上步骤处理取得的值转换为目标字段的类型并返回
@Nullable public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set
autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); try { Object shortcut = descriptor.resolveShortcut(this); if (shortcut != null) { return shortcut; } Class> type = descriptor.getDependencyType(); Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { if (value instanceof String) { String strVal = resolveEmbeddedValue((String) value); BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); value = evaluateBeanDefinitionString(strVal, bd); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); try { return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor()); } catch (UnsupportedOperationException ex) { // A custom TypeConverter which does not support TypeDescriptor resolution... return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); } } Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); if (multipleBeans != null) { return multipleBeans; } Map matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.isEmpty()) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } return null; } String autowiredBeanName; Object instanceCandidate; if (matchingBeans.size() > 1) { autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (autowiredBeanName == null) { if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans); } else { // In case of an optional Collection/Map, silently ignore a non-unique case: // possibly it was meant to be an empty collection of multiple regular beans // (before 4.3 in particular when we didn't even look for collection beans). return null; } } instanceCandidate = matchingBeans.get(autowiredBeanName); } else { // We have exactly one match. Map.Entry entry = matchingBeans.entrySet().iterator().next(); autowiredBeanName = entry.getKey(); instanceCandidate = entry.getValue(); } if (autowiredBeanNames != null) { autowiredBeanNames.add(autowiredBeanName); } if (instanceCandidate instanceof Class) { instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); } Object result = instanceCandidate; if (result instanceof NullBean) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } result = null; } if (!ClassUtils.isAssignablevalue(type, result)) { throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass()); } return result; } finally { ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); } } -
AbstractBeanFactory#resolveEmbeddedValue() 方法比较简单,就是遍历内部缓存的 StringValueResolver 列表,去获取目标属性值。在 2.2节步骤5 中,我们已经注册一个 lambda 表达式 作为 StringValueResolver 在容器内部,则此处会触发PropertySourcesPlaceholderConfigurer#processProperties() 中构造的表达式执行
public String resolveEmbeddedValue(@Nullable String value) { if (value == null) { return null; } String result = value; for (StringValueResolver resolver : this.embeddedValueResolvers) { result = resolver.resolveStringValue(result); if (result == null) { return null; } } return result; } -
PropertySourcesPlaceholderConfigurer#processProperties() 中构造的表达式如下,可以看到此处最终使用目标键获取属性的操作是在调用的 PropertySourcesPropertyResolver#resolveRequiredPlaceholders() 方法中
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, final ConfigurablePropertyResolver propertyResolver) throws BeansException { propertyResolver.setPlaceholderPrefix(this.placeholderPrefix); propertyResolver.setPlaceholderSuffix(this.placeholderSuffix); propertyResolver.setValueSeparator(this.valueSeparator); StringValueResolver valueResolver = strVal -> { String resolved = (this.ignoreUnresolvablePlaceholders ? propertyResolver.resolvePlaceholders(strVal) : propertyResolver.resolveRequiredPlaceholders(strVal)); if (this.trimValues) { resolved = resolved.trim(); } return (resolved.equals(this.nullValue) ? null : resolved); }; ...... } -
PropertySourcesPropertyResolver#resolveRequiredPlaceholders() 由其父类 AbstractPropertyResolver#resolveRequiredPlaceholders()实现,主要流程分为两步:
- 调用 AbstractPropertyResolver#createPlaceholderHelper() 方法创建 PropertyPlaceholderHelper对象
- 调用 AbstractPropertyResolver#doResolvePlaceholders() 方法,进而调用 PropertyPlaceholderHelper#replacePlaceholders() 方法获取属性值,处理原字符串替换
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException { if (this.strictHelper == null) { this.strictHelper = createPlaceholderHelper(false); } return doResolvePlaceholders(text, this.strictHelper); } private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) { return helper.replacePlaceholders(text, this::getPropertyAsRawString); } -
PropertyPlaceholderHelper#replacePlaceholders() 方法只是个入口,核心在 PropertyPlaceholderHelper#parseStringValue() 方法的实现,重要逻辑如下:
- 递归查找目标字符串中 ${} 包裹的字符串,直到最里层
- 使用分隔符 : 切割 ${} 包裹的字符串,将其前半部分作为入参调用 PlaceholderResolver#resolvePlaceholder() 方法取容器中的目标属性值(没有取到则将分隔符 : 后面的字符串作为目标值),替换掉原字符串部分
- 递归收束,最终返回给调用方的即为替换掉了 ${} 包裹内容的字符串
public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) { Assert.notNull(value, "'value' must not be null"); return parseStringValue(value, placeholderResolver, null); } protected String parseStringValue( String value, PlaceholderResolver placeholderResolver, @Nullable SetvisitedPlaceholders) { int startIndex = value.indexOf(this.placeholderPrefix); if (startIndex == -1) { return value; } StringBuilder result = new StringBuilder(value); while (startIndex != -1) { int endIndex = findPlaceholderEndIndex(result, startIndex); if (endIndex != -1) { String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex); String originalPlaceholder = placeholder; if (visitedPlaceholders == null) { visitedPlaceholders = new HashSet<>(4); } if (!visitedPlaceholders.add(originalPlaceholder)) { throw new IllegalArgumentException( "Circular placeholder reference '" + originalPlaceholder + "' in property definitions"); } // Recursive invocation, parsing placeholders contained in the placeholder key. placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders); // Now obtain the value for the fully resolved key... String propVal = placeholderResolver.resolvePlaceholder(placeholder); if (propVal == null && this.valueSeparator != null) { int separatorIndex = placeholder.indexOf(this.valueSeparator); if (separatorIndex != -1) { String actualPlaceholder = placeholder.substring(0, separatorIndex); String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length()); propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder); if (propVal == null) { propVal = defaultValue; } } } if (propVal != null) { // Recursive invocation, parsing placeholders contained in the // previously resolved placeholder value. propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders); result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal); if (logger.isTraceEnabled()) { logger.trace("Resolved placeholder '" + placeholder + "'"); } startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length()); } else if (this.ignoreUnresolvablePlaceholders) { // Proceed with unprocessed value. startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length()); } else { throw new IllegalArgumentException("Could not resolve placeholder '" + placeholder + "'" + " in value "" + value + """); } visitedPlaceholders.remove(originalPlaceholder); } else { startIndex = -1; } } return result.toString(); } -
回到步骤11第3步,SpEL 表达式的解析入口为 AbstractBeanFactory#evaluateBeanDefinitionString() 方法,此处使用了 Spring 中 SpEL 表达式模块的相关 API, 本文不做进一步分析,有兴趣的读者可以自行搜索学习
protected Object evaluateBeanDefinitionString(@Nullable String value, @Nullable BeanDefinition beanDefinition) { if (this.beanexpressionResolver == null) { return value; } Scope scope = null; if (beanDefinition != null) { String scopeName = beanDefinition.getScope(); if (scopeName != null) { scope = getRegisteredScope(scopeName); } } return this.beanexpressionResolver.evaluate(value, new BeanexpressionContext(this, scope)); } -
回到步骤11第4步,经过类型转换器将处理得到的属性值转换为目标字段的类型后,方法栈再回到步骤9第2步,一次属性注入的流程基本结束。类型转换的部分本文不再分析,读者有兴趣可以自行深入,至此 @Value 实现原理的分析暂告段落



