栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot 注解 @Value 实现源码分析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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 标注的属性进行依赖注入

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 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;
     }
    
  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) () -> {
     				((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. 新建封装了属性来源列表 propertySources 的 PropertySourcesPropertyResolver 对象,该对象主要负责从属性源中获取指定的属性值
      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_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 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);
       	}
       }
      
    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 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 elements = 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);
      }
      
    7. AutowiredAnnotationBeanPostProcessor#findAutowiredAnnotation() 方法其实就是查看字段或者方法上是否存在指定的三个注解 @Autowired、@Value、@Inject

       @Nullable
       private MergedAnnotation findAutowiredAnnotation(AccessibleObject ao) {
       	MergedAnnotations annotations = MergedAnnotations.from(ao);
       	for (Class 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 checkedElements = 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);
       		}
       	}
       }
      
    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 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 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 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);
      	}
      }
      
    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 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 实现原理的分析暂告段落

    转载请注明:文章转载自 www.mshxw.com
    我们一直用心在做
    关于我们 文章归档 网站地图 联系我们

    版权所有 (c)2021-2022 MSHXW.COM

    ICP备案号:晋ICP备2021003244-6号