Spring @Value的注解使用和原理
介绍
@Value注解在Spring开发中是一个使用很频繁的注解,在项目开发中,我们通常需要读取配置文件中的一些信息,对于SpringBoot项目,我们一般从yml文件中读取,如果我们自定义了配置文件,那么就可以配合@PropertySource注解来获取配置文件的配置项,当然,@Value不单单能读取配置文件,还能读取系统属性,还可以读取其他bean的属性,本章就来详细介绍@Value注解的使用和对源码进行分析。
使用
如下我们对value的使用进行详细介绍,value可以注入配置文件的属性,注入其它bean的属性,注册spring中自己实现的一些属性,比如操作系统信息。
属性类
MyProperties是一个bean,里面定义了一些属性,一般在项目中,如果需要全局使用某个配置信息,我们通常会定义一个属性类,然后在需要使用的地方直接注入,比如系统中我们需要存储大量的文件,文件是存储在文件服务器上面,数据库只存储文件所在文件系统的目录路径,而不会存储具体的ip地址,如果我们存储了能直接访问文件的链接,后续如果进行文件迁移,那么这些链接就不好处理,所以应该只存储文件在文件服务器的目录路径,那么返回给前端显示的时候,再获取文件服务器地址进行拼接就可以。
-
/**
-
* 功能说明: 属性配置类
-
* <p>
-
* Original @Author: steakliu-刘牌, 2023-04-27 10:08
-
* <p>
-
* Copyright (C)2020-2022 steakliu All rights reserved.
-
*/
-
@Data
-
@Component
-
public class MyProperties {
-
/**
-
* 注入其他bean的属性
-
*/
-
@Value("#{valueBean.username}")
-
private String username;
-
/**
-
* 注入配置文件属性
-
*/
-
@Value("${minio.url}")
-
private String minioUrl;
-
/**
-
* 注入操作系统属性
-
*/
-
@Value("#{systemProperties['os.name']}")
-
private String os;
-
}
-
复制代码
配置类
配置类主要就是使用@PropertySource
注解来获取配置配置文件的属性。
-
@Configuration
-
@PropertySource("classpath:minio.properties")
-
public class ValueConfiguration {
-
-
}
-
复制代码
配置文件minio.properties
配置文件里面就放了一个minio的地址
-
minio.url=http://www.gss.cn/
-
复制代码
通过上面的配置,我们就可以在需要使用minio地址的地方注入MyProperties这bean就可以,可能有些人会觉得麻烦,还需要注入bean,直接写在一个常量里面不就行,其实不然,这样做更加的规范,做到了配置和代码的分离,不同的环境的地址不同,或者发生文件迁移,就可以直接修改配置文件,还有配置文件可以写入注册中心,可以更具一定的策略进行修改后刷新,@Value注解只是获取配置文件属性的一种方式,在SpringBoot中,@ConfigurationProperties
使用起来也很方便。
原理解析
下面对@Value的原理进行解析,因为我们使用@Value大多时候是放在字段上面,并且要使用在一个Bean中,那么我们知道bean在实例化的时候需要进行属性填充,就会对这些属性进行赋值,所以下面就从实例化bean开始对@Value进行解析。
解析属性
我们从AbstractAutowireCapableBeanFactory
类这里开始,在类中进入doCreateBean()
方法,然后进入applyMergedBeanDefinitionPostProcessors
,最终会进入AutowiredAnnotationBeanPostProcessor
后置处理器中,@Autowired,@Value,@Inject都是它进行处理,下面我们看最主要的部分buildAutowiringMetadata
。
如下代码,Spring使用反射获取字段,如果是字段被static修饰,那么在此处是会被排除,使用的是Modifier.isStatic(int mod)
方法,通过反射拿到字段后,组装后加入一个名字为injectionMetadataCache
的Map中,后面属性填充会直接从这个缓存中获取。
-
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
-
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 AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement(field, required));
-
}
-
});
-
}
-
while (targetClass != null && targetClass != Object.class);
-
-
return InjectionMetadata.forElements(elements, clazz);
-
}
-
复制代码
属性填充
属性填充阶段进入的是对bean的属性进行赋值,这是Spring生命周期中很重要的一个阶段,方法是populateBean
,也在AbstractAutowireCapableBeanFactory
类中,接着会调用AutowiredAnnotationBeanPostProcessor
中的postProcessProperties
方法,然后往下继续执行,核心代码如下,如下就是给每个属性赋值,往下执行还有很多逻辑处理,如解析@Value
注解的表达式,然后根据表达式去获取对应的值等,就不深入去解析。
-
protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
-
Field field = (Field) this.member;
-
Object value;
-
if (this.cached) {
-
try {
-
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
-
} catch (NoSuchBeanDefinitionException ex) {
-
// Unexpected removal of target bean for cached argument -> re-resolve
-
value = resolveFieldValue(field, bean, beanName);
-
}
-
} else {
-
value = resolveFieldValue(field, bean, beanName);
-
}
-
if (value != null) {
-
ReflectionUtils.makeAccessible(field);
-
field.set(bean, value);
-
}
-
}
-
复制代码
总结
上面对@Value的使用和原理进行了介绍,其实@Value,@Autowired,@Resource,@Inject这几个的作用都是进行属性装配,只不过他们的方式各有不同,@Value,@Autowired,@Inject是使用AutowiredAnnotationBeanPostProcessor
后置处理器进行处理,@Resource则使用CommonAnnotationBeanPostProcessor
后置处理器进行处理。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgjbbci
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13