快捷搜索:  汽车  科技

如何读取value的值,value属性是如何赋值的

如何读取value的值,value属性是如何赋值的我们看下resolveEmbeddedValue方法是如何获取到属性值的。resolveEmbeddedValue方法是从MutablePropertySources中获取到属性值.具体代码定位到DefaultListableBeanFactory类的doResolveDependency方法:@Nullable public Object doResolveDependency(DependencyDescriptor descriptor @Nullable String beanName @Nullable Set<String> autowiredBeanNames @Nullable TypeConverter typeConverter) throws BeansException { InjectionPoint previousInjecti

喜欢Spring源码的朋友,点点关注,您的支持是我前进的动力[赞][握手][给力]。

对@value属性赋值是发生在bean属性填充阶段,也就是populateBean方法。

下面是相关代码的时序图:

如何读取value的值,value属性是如何赋值的(1)

时序图

具体代码定位到DefaultListableBeanFactory类的doResolveDependency方法:

@Nullable public Object doResolveDependency(DependencyDescriptor descriptor @Nullable String beanName @Nullable Set<String> autowiredBeanNames @Nullable TypeConverter typeConverter) throws BeansException { InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); try { Class<?> type = descriptor.getDependencyType(); //获得@Value注解的value值 Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { if (value instanceof String) { //解析value值,并且从MutablePropertySources中获取属性值 String strVal = resolveEmbeddedValue((String) value); BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); value = evaluateBeanDefinitionString(strVal bd); } Typeconverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); return (descriptor.getField() != null ? converter.convertIfNecessary(value type descriptor.getField()) : converter.convertIfNecessary(value type descriptor.getMethodParameter())); } ...... return result; } finally { ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint); } }

getSuggestedValue是获得@Value注解的value值 例如我们在某个类里面定义了cc属性

@Value("${test.cc}") private String cc;

getSuggestedValue获取到值是${test.cc}。

resolveEmbeddedValue方法是从MutablePropertySources中获取到属性值.

我们看下resolveEmbeddedValue方法是如何获取到属性值的。

@Override @Nullable 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; }

embeddedValueResolvers是CopyOnWriteArrayList类型,我们期望的resolver是从environment中的MutablePropertySources获取到配置项的值。

我们通过idea,看到StringValueResolver的实现类有PlaceholderResolvingStringValueResolver,StaticStringValueResolver,EmbeddedValueResolver,这几个实现类的resolveStringValue都没有从MutablePropertySources取值,这里的StringValueResolver真正的实现类在哪里呢?这个问题困惑了我好久,下面我们一起看下真正的实现类在哪里

众里寻她千百度,蓦然回首....

在idea中查找embeddedValueResolvers的Usages,找到了PropertySourcesPlaceholderConfigurer类,它是BeanFactoryPostProcessor的实现类。

@Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { //....省略前面的代码 processProperties(beanFactory new PropertySourcesPropertyResolver(this.propertySources)); this.appliedPropertySources = this.propertySources; }

postProcessBeanFactory方法中调用了processProperties方法,点进方法查看一下,关键点就在里面

protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess final ConfigurablePropertyResolver propertyResolver) throws BeansException { propertyResolver.setPlaceholderPrefix(this.placeholderPrefix); propertyResolver.setPlaceholderSuffix(this.placeholderSuffix); propertyResolver.setValueSeparator(this.valueSeparator); //创建了匿名的StringValueResolver的实现类,这才是获取@Value值的处理类 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); }

在上面的方法内部创建了匿名的StringValueResolver的实现类,实现了resolveStringValue方法,doProcessProperties方法会将StringValueResolver对象加入到embeddedValueResolvers中去。

匿名的StringValueResolver的实现类的resolveStringValue方法调用的PropertySourcesPropertyResolver类的处理方法,而参数是MutablePropertySources类型的,内容包含了apollo配置,环境变量,项目内的properties文件,yml文件等配置。

一言以蔽之,真正获取属性值的类是PropertySourcesPropertyResolver

如何从MutablePropertySources中获取某个配置项的?

具体处理在PropertySourcesPropertyResolver类的getPropertyAsRawString方法

protected String getPropertyAsRawString(String key) { return getProperty(key String.class false); } @Nullable protected <T> T getProperty(String key Class<T> targetValueType boolean resolveNestedPlaceholders) { if (this.propertySources != null) { for (PropertySource<?> propertySource : this.propertySources) { if (logger.isTraceEnabled()) { logger.trace("Searching for key '" key "' in PropertySource '" propertySource.getName() "'"); } Object value = propertySource.getProperty(key); if (value != null) { if (resolveNestedPlaceholders && value instanceof String) { value = resolveNestedPlaceholders((String) value); } logKeyFound(key propertySource value); return convertValueIfNecessary(value targetValueType); } } } if (logger.isDebugEnabled()) { logger.debug("Could not find key '" key "' in any property source"); } return null; }

getProperty方法会对propertySources进行循环,获取到值,就退出循环。

比如说在apollo和application.properties文件中都存在相同的配置项test.cc,但是值不同,由于apollo配置是放在List的最前面,所以会取apollo里面的值,application.properties内的值会被忽略掉。这就是配置优先级的体现。

总结不易,请关注点赞哦!!!

如何读取value的值,value属性是如何赋值的(2)

猜您喜欢: