在Spring Boot中,配置通常有两个主要来源,即系统配置和自定义配置。
系统配置指的是Spring Boot提供的“开箱即用”的默认配置,如启动和服务器配置server.port、数据库连接spring.datasource、日志设置logging.level等。这些配置主要控制框架和第三方库的行为。
自定义配置通常用于应用程序特定的配置,这些配置不是框架或库提供的,而是为满足特定业务或功能需求而定义的。例如,如果应用程序需要与外部API交互,你可能需要配置该API的URL、超时时间、API密钥等。也可以定义应用程序的版本号、默认语言、默认时区等。
系统配置关注框架和库的行为,而自定义配置更注重业务逻辑和应用程序特有的功能。在实际应用开发中,这两种配置经常同时使用,以确保应用程序能够正常工作并满足特定需求。
在Spring Boot中,为了支持强大且灵活的配置机制,框架提供了@Value和@ConfigurationProperties这两个关键注解。它们都会从配置文件中读取并注入属性值,但各有其特色和适用场景。
@Value允许直接将配置文件中的单个属性值注入Spring bean中的字段、方法参数或构造函数参数。在Spring Boot中,经常使用@Value从application.properties或application.yml中读取配置值。例如,@Value("${app.name}")可以从配置文件中读取app.name的值并将其注入对应的Java字段。
首先,在application.properties文件中加入以下自定义内容。
app.name=MyApplication
在1.4.1节创建的demo项目中,加入测试用的bean,命名为MyAppProperties,为了方便测试,将此类创建在test目录的com.example.demo包下,代码如下。
import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class MyAppProperties { // 读取配置文件中的app.name配置项 @Value("${app.name}") private String appName; public String getAppName() { return appName; } public void setAppName(String appName) { this.appName = appName; } }
上述代码创建了名为MyAppProperties的Java类,共使用了两个注解,分别为@Component和@Value。
(1)@Component是Spring框架中的一个核心注解,它表示该类是一个组件,即一个Spring bean。Spring会自动检测应用程序中所有带有@Component注解的类,并将它们注册为Spring应用上下文中的bean,由Spring容器进行统一管理。
@Component是其他许多Spring注解的基础,如@Service、@Repository和@Controller。这些都是特殊化的@Component注解,各自具有特定的用途。这些注解在后续的章节中还会详细介绍。带有@Component的类可以使用@Autowired、@Resource或@Inject注解来自动注入依赖。
(2)@Value("${app.name}")用于读取application.properties配置文件中app.name配置项的属性值。
在项目test目录自带的DemoApplicationTests类中加入以下单元测试代码,用于测试@Value注解。
@SpringBootTest class DemoApplicationTests { @Autowired private MyAppProperties appProperties; @Test void getProperties(){ System.out.printf(appProperties.getAppName());; } }
这段代码中首先使用了@SpringBootTest注解告诉Spring Boot为该测试类创建一个完整的应用上下文,通常包括所有的应用组件,如beans、配置类和其他依赖项。这使得我们可以在真实的Spring Boot环境中运行测试。
然后在DemoApplicationTests类中声明了一个私有字段appProperties,其类型为MyAppProperties,其上的@Autowired注解表示Spring Boot在启动时应该自动注入一个MyAppProperties类型的bean到该字段中。能够注入的前提是MyAppProperties类应该带有类似@Component这样的注解。
接着定义了名为getProperties的测试方法,@Test注解标识这是一个JUnit测试方法。
在测试方法内,我们调用appProperties.getAppName()方法获取应用名称,并使用System.out.printf将其打印到控制台。
如果MyAppProperties未正确配置或其他任何原因导致bean注入失败,则此测试将不会通过。
虽然@Value是以一种简单并且直观的方式来注入配置值,但当需要注入大量相关的配置属性时,使用@ConfigurationProperties通常是更好的选择,该注解允许你将配置文件中的多个相关属性绑定到一个Java bean,使得配置更加结构化和类型更加安全。例如,使用@ConfigurationProperties(prefix = "app")可以将所有带有app前缀的属性绑定到一个bean。
首先,在application.properties文件中加入以下自定义内容。
app.custom.name=MyApplication app.custom.timeout=300
在demo项目中,加入测试用的bean,命名为CustomProperties,为了方便测试,将此类创建在test目录的com.example.demo包下,代码如下。
@Component @ConfigurationProperties(prefix = "app.custom") public class CustomProperties { private String name; private int timeout; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getTimeout() { return timeout; } public void setTimeout(int timeout) { this.timeout = timeout; } }
在上面的例子中,prefix = "app.custom"指示@ConfigurationProperties查找前缀为app.custom的所有属性,如app.custom.name和app.custom.timeout。为了后续在项目中使用该类,需要确保AppProperties类能被Spring Boot识别并处理。因此将其标记为@Component。
在DemoApplicationTests类中加入以下单元测试代码,用于测试是否生效。
@SpringBootTest class DemoApplicationTests { @Test void contextLoads() { } @Autowired private MyAppProperties appProperties; @Autowired private CustomProperties customProperties; @Test void getProperties(){ System.out.println(appProperties.getAppName());; System.out.println(customProperties.getName()); System.out.println(customProperties.getTimeout()); } }
上述代码中,首先通过@Autowired注解注入了customProperties实例,然后在getProperties()测试方法中调用customProperties.getName()和customProperties.getTimeout()方法获取配置信息并打印至控制台。
为了选择合适的配置注入方法,开发者需要根据具体需求进行权衡。如果只是需要注入少量的属性,@Value可能是更简单的选择。然而,对于需要结构化和集中管理的大型配置,或者需要利用类型安全、验证和复杂属性的优势,@ConfigurationProperties显然是更好的选择。