SpringBoot 注解 @Value 实现源码分析

文章目录

  • 前言
  • 1. @Value 的源码处理流程
  • 2. 源码分析
      • 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 标注的属性进行依赖注入

SpringBoot 注解 @Value 实现源码分析_第1张图片

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 的内部属性依赖
    public static Set<BeanDefinitionHolder> 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<BeanDefinitionHolder> 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;
     }
    
  2. 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<Object>) () -> {
     				((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(DefaultListableBeanFactory.this);
     				return null;
     			}, getAccessControlContext());
     		}
     		else {
     			((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this);
     		}
     	}
     	this.autowireCandidateResolver = autowireCandidateResolver;
     }
    

2.2 属性处理器 PropertySourcesPropertyResolver 的注册

  1. 在 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();
     }
    
    }
    
  2. PropertySourcesPlaceholderConfigurer 实现了 BeanFactoryPostProcessor 接口,则当容器刷新时创建 Bean 工厂后会被用于对 Bean 工厂进行后置处理,触发 PropertySourcesPlaceholderConfigurer#postProcessBeanFactory() 方法,该方法比较重要的处理如下:

    1. 初始化属性来源列表 propertySources,可以看到此处会将 Environment 作为属性值来源
    2. 新建封装了属性来源列表 propertySourcesPropertySourcesPropertyResolver 对象,该对象主要负责从属性源中获取指定的属性值
    3. 调用 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>(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;
     }
    
  3. PropertySourcesPlaceholderConfigurer#processProperties() 方法的重要处理如下:

    1. 通过 propertyResolver.setPlaceholderPrefix() 等方法调用,为 PropertySourcesPropertyResolver 对象设置属性解析的前后缀为 ${},分隔符为 :
    2. 使用 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);
     }
    
  4. 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);
     }
    
  5. AbstractBeanFactory#addEmbeddedValueResolver() 方法的实现如下,可以看到只是个内部缓存动作,至此解析由 ${} 包裹的属性的属性处理器已经注册到容器内部

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

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

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

     @Override
     @SuppressWarnings("unchecked")
     public <T> T createBean(Class<T> beanClass) throws BeansException {
     	// Use prototype bean definition, to avoid registering bean as dependent bean.
     	RootBeanDefinition bd = new RootBeanDefinition(beanClass);
     	bd.setScope(SCOPE_PROTOTYPE);
     	bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader());
     	return (T) createBean(beanClass.getName(), bd, null);
     }
    
     @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);
     	}
     }
    
  2. AbstractAutowireCapableBeanFactory#doCreateBean() 方法比较长,核心为以下两步:

    1. 调用 AbstractAutowireCapableBeanFactory#createBeanInstance() 方法创建属性空白的 Bean 实例
    2. 调用 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);
     				Set<String> actualDependentBeans = 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;
     }
    
  3. 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);
     	}
     }
    
  4. 2.1节中注册的 AutowiredAnnotationBeanPostProcessor 就实现了 InstantiationAwareBeanPostProcessor 接口,则此处 AutowiredAnnotationBeanPostProcessor#postProcessProperties() 将被触发调用,可以看到此处的关键处理有两步:

    1. 调用 AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata() 方法创建注入元数据对象 InjectionMetadata
    2. 调用 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;
     }
    
  5. 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;
     }
    
  6. AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata() 方法实现如下,可以看到这里会将目标类定义的字段 Field方法 Method 分别处理。具体逻辑是通过 AutowiredAnnotationBeanPostProcessor#findAutowiredAnnotation() 方法获取字段或者方法上标注的特定注解,如果能获取到说明需要处理依赖注入,则生成对应的 InjectedElement 实例,代表一个需要处理注入的元素

    private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
    	if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
    		return InjectionMetadata.EMPTY;
    	}
    
    	List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
    	Class<?> targetClass = clazz;
    
    	do {
    		final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
    
    		ReflectionUtils.doWithLocalFields(targetClass, field -> {
    			MergedAnnotation<?> ann = findAutowiredAnnotation(field);
    			if (ann != null) {
    				if (Modifier.isStatic(field.getModifiers())) {
    					if (logger.isInfoEnabled()) {
    						logger.info("Autowired annotation is not supported on static fields: " + field);
    					}
    					return;
    				}
    				boolean required = determineRequiredStatus(ann);
    				currElements.add(new AutowiredFieldElement(field, required));
    			}
    		});
    
    		ReflectionUtils.doWithLocalMethods(targetClass, method -> {
    			Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
    			if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
    				return;
    			}
    			MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
    			if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
    				if (Modifier.isStatic(method.getModifiers())) {
    					if (logger.isInfoEnabled()) {
    						logger.info("Autowired annotation is not supported on static methods: " + method);
    					}
    					return;
    				}
    				if (method.getParameterCount() == 0) {
    					if (logger.isInfoEnabled()) {
    						logger.info("Autowired annotation should only be used on methods with parameters: " +
    								method);
    					}
    				}
    				boolean required = determineRequiredStatus(ann);
    				PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
    				currElements.add(new AutowiredMethodElement(method, required, pd));
    			}
    		});
    
    		elements.addAll(0, currElements);
    		targetClass = targetClass.getSuperclass();
    	}
    	while (targetClass != null && targetClass != Object.class);
    
    	return InjectionMetadata.forElements(elements, clazz);
    }
    
  7. 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;
     }
    
  8. 经过以上步骤,Bean 对象需要处理依赖注入的元素都封装在了 InjectionMetadata 对象中,回到步骤4第2步InjectionMetadata#inject() 方法遍历其内部待填充属性的元素,调用其InjectedElement#inject()进行属性注入

    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) {
     			if (logger.isTraceEnabled()) {
     				logger.trace("Processing injected element of bean '" + beanName + "': " + element);
     			}
     			element.inject(target, beanName, pvs);
     		}
     	}
     }
    
  9. 本文以字段属性注入为例,AutowiredFieldElement#inject() 方法的实现如下,核心逻辑可分为两步:

    1. 调用 DefaultListableBeanFactory#resolveDependency() 从容器中获取字段的属性值
    2. 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());
     			Set<String> autowiredBeanNames = 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);
     		}
     	}
    
  10. DefaultListableBeanFactory#resolveDependency() 会做常规的判断,核心是调用DefaultListableBeanFactory#doResolveDependency() 方法

    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;
    	}
     }
    
  11. 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() 方法将以上步骤处理取得的值转换为目标字段的类型并返回
    @Nullable
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
    		@Nullable Set<String> 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<String, Object> 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<String, Object> 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);
    	}
    }
    
  12. 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;
    }
    
  13. 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);
    	};
    
    	......
    }
    
  14. PropertySourcesPropertyResolver#resolveRequiredPlaceholders() 由其父类 AbstractPropertyResolver#resolveRequiredPlaceholders()实现,主要流程分为两步:

    1. 调用 AbstractPropertyResolver#createPlaceholderHelper() 方法创建 PropertyPlaceholderHelper对象
    2. 调用 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);
    }
    
  15. PropertyPlaceholderHelper#replacePlaceholders() 方法只是个入口,核心在 PropertyPlaceholderHelper#parseStringValue() 方法的实现,重要逻辑如下:

    1. 递归查找目标字符串中 ${} 包裹的字符串,直到最里层
    2. 使用分隔符 : 切割 ${} 包裹的字符串,将其前半部分作为入参调用 PlaceholderResolver#resolvePlaceholder() 方法取容器中的目标属性值(没有取到则将分隔符 : 后面的字符串作为目标值),替换掉原字符串部分
    3. 递归收束,最终返回给调用方的即为替换掉了 ${} 包裹内容的字符串
    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 Set<String> visitedPlaceholders) {
    
    	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();
    }
    
  16. 回到步骤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));
     }
    
    
  17. 回到步骤11第4步,经过类型转换器将处理得到的属性值转换为目标字段的类型后,方法栈再回到步骤9第2步,一次属性注入的流程基本结束。类型转换的部分本文不再分析,读者有兴趣可以自行深入,至此 @Value 实现原理的分析暂告段落

你可能感兴趣的:(Spring,源码分析,restful,spring,java)