我们来梳理一下最常见的几种用法:
方法一:注入配置文件中的属性(最常用)
这是最核心的用法。假设我们有一个标准的 spring boot 项目,其配置文件 application.properties
内容如下:
src/main/resources/application.properties
# 应用信息 app.name=my awesome app app.version=1.2 # 作者信息 author.name=alice author.email=alice@example.com # 功能开关和配置 feature.email.enabled=true max.pool.size=100
现在,我们想创建一个 appinfoservice
组件,并将这些配置值注入进去。
appinfoservice.java
import org.springframework.beans.factory.annotation.value; import org.springframework.stereotype.service; @service public class appinfoservice { // 1. 注入字符串 @value("${app.name}") private string appname; // 2. 注入数字(spring会自动进行类型转换) @value("${app.version}") private double appversion; @value("${max.pool.size}") private int maxpoolsize; // 3. 注入布尔值 @value("${feature.email.enabled}") private boolean isemailenabled; // 4. 提供默认值 // 如果配置文件中没有 `app.description`,则使用默认值 "a great application" @value("${app.description:a great application}") private string appdescription; public void displayappinfo() { system.out.println("application name: " + appname); system.out.println("application version: " + appversion); system.out.println("max pool size: " + maxpoolsize); system.out.println("is email feature enabled: " + isemailenabled); system.out.println("description: " + appdescription); } }
关键点解读:
- 语法
\${...}
:这是属性占位符 (property placeholder)。它告诉 spring:“请到我的环境配置(包括application.properties
、系统变量、jvm参数等)中去查找...
这个键,并把它的值注入进来。” - 自动类型转换:你只需要定义好字段的类型(
double
,int
,boolean
),spring 的类型转换服务会自动将配置文件中的字符串值(如"1.2"
)转换成相应的 java 类型。 - 提供默认值
:${...}
:使用冒号:
可以在属性不存在时提供一个默认值。这可以防止因为缺少某个可选配置而导致应用启动失败。
方法二:使用 spring 表达式语言 (spel)
@value
不仅能注入属性,还能执行更强大的 spring expression language (spel) 表达式。spel 表达式使用 #{...}
语法。
spel 可以让你:
- 引用其他 bean 的属性。
- 执行方法调用。
- 进行数学运算。
- 引用系统属性等。
一些例子:
import org.springframework.beans.factory.annotation.value; import org.springframework.stereotype.component; @component public class spelexamples { // 1. 执行简单的数学运算 @value("#{10 * 60}") // 注入 600 private int secondsintenminutes; // 2. 引用另一个bean的属性 // 假设容器中有一个名为 appinfoservice 的bean @value("#{appinfoservice.appname}") private string anotherappname; // 3. 调用静态方法 @value("#{t(java.lang.math).random() * 100.0}") private double randomnumber; // 4. 引用系统属性 @value("#{systemproperties['user.home']}") private string userhomedirectory; // 5. 结合属性占位符使用 // 先从配置文件找到 `some.value`,如果不存在则使用 `default`,然后转为大写 @value("#{'${some.value:default}'.touppercase()}") private string uppercasevalue; public void display() { system.out.println("seconds in 10 minutes: " + secondsintenminutes); system.out.println("copied app name: " + anotherappname); system.out.println("random number: " + randomnumber); system.out.println("user home: " + userhomedirectory); system.out.println("uppercase value: " + uppercasevalue); } }
\${...}
vs #{...}
的区别
这也是个常见的面试题:
\${...}
:属性占位符,主要用于从外部配置文件中获取值。它是静态的,值在应用启动时就基本确定了。#{...}
:spel 表达式,用于执行动态的计算和逻辑。它可以在运行时计算出一个值。
方法三:注入硬编码的字符串
虽然不常用,但你也可以直接注入一个写死的字符串。
@value("this is a hardcoded message") private string message;
这种方式的灵活性很低,通常只在测试或非常简单的场景下使用。
总结
注入方式 | 语法 | 数据来源 | 主要用途 | 灵活性 |
---|---|---|---|---|
属性占位符 | @value("${...}") | 配置文件、环境变量等 | 将外部配置注入代码,实现代码与配置解耦。 | 非常高 |
spel 表达式 | @value("#{...}") | bean 属性、方法调用、运算结果 | 执行动态计算,实现更复杂的注入逻辑。 | 极高 |
硬编码值 | @value("...") | 固定的字符串 | 测试或注入不会改变的常量。 | 非常低 |
通过 @value
注解,spring ioc 容器不仅能管理对象之间的依赖关系(@autowired
),还能完美地管理对象与外部配置值之间的关系,从而让我们的应用程序更加健壮、灵活和易于维护。这同样是控制反转思想的体现:组件不再自己去读取配置文件,而是被动地等待容器将配置值“注入”给它。
以上就是spring ioc注入一些简单的值的几种常见方法的详细内容,更多关于spring ioc注入值的资料请关注代码网其它相关文章!