10.扫描注解
在 Spring Boot 中,@EnableConfigurationProperties
和 @ConfigurationPropertiesScan
是两个用于显式启用和管理 @ConfigurationProperties
类的注解。它们提供了更灵活的方式来注册和扫描 @ConfigurationProperties
类,尤其是在某些复杂场景或非标准的配置类路径下(非根包路径)。
@EnableConfigurationProperties
@EnableConfigurationProperties
注解用于显式启用 @ConfigurationProperties
的支持。它通常用于以下场景:
- 当你没有使用
@SpringBootApplication
注解(它已经隐式启用了@ConfigurationProperties
支持)。 - 当你需要手动注册一个或多个
@ConfigurationProperties
类时。
使用 @EnableConfigurationProperties
假设你有一个 @ConfigurationProperties
类 MyAppProperties
,但没有使用 @SpringBootApplication
注解,你可以通过在启动类加上 @EnableConfigurationProperties
来启用它。
MyAppProperties.java
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "myapp")
public class MyAppProperties {
private String name;
private int port;
// Getters and Setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
MainApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@SpringBootApplication
// 显式启用和管理 MyAppProperties.class
//@EnableConfigurationProperties( 待开启的类名.class)
// //@EnableConfigurationProperties({User.class}) 另一种写法
@EnableConfigurationProperties(MyAppProperties.class)
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
在这个例子中,@EnableConfigurationProperties
被用来显式注册 MyAppProperties
类。如果你的 @ConfigurationProperties
类没有被自动扫描到(例如,它不在组件扫描的路径下),这种方式非常有用。
@ConfigurationPropertiesScan
@ConfigurationPropertiesScan
是 Spring Boot 2.4 引入的一个注解,用于显式指定 @ConfigurationProperties
类的扫描路径。它类似于 @ComponentScan
,但专门用于 @ConfigurationProperties
类。
使用 @ConfigurationPropertiesScan
假设你的 @ConfigurationProperties
类位于一个非标准的包路径下(不在根包路径),你可以使用 @ConfigurationPropertiesScan
来指定扫描路径。
MyAppProperties.java
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "myapp")
public class MyAppProperties {
private String name;
private int port;
// Getters and Setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}
MainApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
@SpringBootApplication
@ConfigurationPropertiesScan("com.example.config") // 指定扫描路径
// @ConfigurationPropertiesScan("包名")
// @ConfigurationPropertiesScan (basePackages = {"com.yanyu"})
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
在这个例子中,@ConfigurationPropertiesScan
被用来指定扫描路径 com.example.config
,Spring Boot 会在这个包路径下查找带有 @ConfigurationProperties
注解的类并注册为 Bean。
总结
@EnableConfigurationProperties
:用于显式启用@ConfigurationProperties
支持,通常用于手动注册一个或多个@ConfigurationProperties
类。@ConfigurationPropertiesScan
:用于显式指定@ConfigurationProperties
类的扫描路径,类似于@ComponentScan
,但专门用于@ConfigurationProperties
类。
在大多数情况下,如果你使用了 @SpringBootApplication
注解,Spring Boot 会自动启用 @ConfigurationProperties
支持并扫描默认的包路径。
如果你需要更灵活的控制,可以使用 @EnableConfigurationProperties
或 @ConfigurationPropertiesScan
。
案例
@EnableConfigurationProperties
User.java
package com.yanyu.bean2.pk1;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.Objects;
/**
* @Author yanyu666_508200729@qq.com
* @Date 2025/3/24 23:14
* @description:
*/
@ConfigurationProperties(prefix = "user")
public class User {
String name;
Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(name, user.name) && Objects.equals(age, user.age);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
启动类
package com.yanyu.bean2;
import com.yanyu.bean2.pk1.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@SpringBootApplication
// 显示开启 `@ConfigurationProperties
//@EnableConfigurationProperties({User.class})
@EnableConfigurationProperties(User.class)
public class Bean2Application {
public static void main(String[] args) {
SpringApplication.run(Bean2Application.class, args);
}
}
test
package com.yanyu.bean2;
import com.yanyu.bean2.pk1.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Bean2ApplicationTests {
// 取出对象
@Autowired
User user;
@Test
void contextLoads() {
}
@Test
void test1(){
System.out.println(user);
}
}
@ConfigurationPropertiesScan
User.java
package com.yanyu;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.Objects;
/**
* @Author yanyu666_508200729@qq.com
* @Date 2025/3/24 23:14
* @description:
*/
@ConfigurationProperties(prefix = "user")
public class User {
String name;
Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(name, user.name) && Objects.equals(age, user.age);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.yanyu.bean2;
import com.yanyu.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@SpringBootApplication
// 显示开启 `@ConfigurationProperties
//@EnableConfigurationProperties({User.class})
//@EnableConfigurationProperties(User.class)
//@ConfigurationPropertiesScan(basePackages = {"同时指定扫描多个包下面的类",""})
@ConfigurationPropertiesScan(basePackages = {"com.yanyu"})
public class Bean2Application {
public static void main(String[] args) {
SpringApplication.run(Bean2Application.class, args);
}
}
11.处理第三方库对象
上面的例子都是在源代码中使用@ConfigurationProperties 注解,如果某个类需要在配置文件中提供数据,但
是没有源代码。此时@ConfigurationProperties 结合@Bean 一起在方法上面使用,利用 bean 去 映射信息到,符合 Javabean 规范的类中,再 利用 @ bean 把对象丢到 IOC 容器
- 情景:
- 没有源代码,只有 .class 或者 .class 打包未一个 . jar
- 例如,引用MySQL驱动后,配置数据库的信息
某个值未 null
no —> 换成 id 解决
application.yml
phone:
name: iqoo
id: v1992
package com.yanyu.bean3.pk1;
import java.util.Objects;
/**
* @Author yanyu666_508200729@qq.com
* @Date 2025/3/25 0:28
* @description:
*/
public class Phone {
String name;
String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getid() {
return id;
}
public void setid(String id) {
this.id = id;
}
@Override
public String toString() {
return "Phone{" +
"name='" + name + '\'' +
", id='" + id + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Phone phone = (Phone) o;
return Objects.equals(name, phone.name) && Objects.equals(id, phone.id);
}
@Override
public int hashCode() {
return Objects.hash(name, id);
}
}
package com.yanyu.bean3.pk1;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
/**
* @Author yanyu666_508200729@qq.com
* @Date 2025/3/24 23:48
* @description:
*/
@Configuration
public class PhoneConfig {
/*在方法上使用 ConfigurationProperties
和 bean
*
* */
// 把下面方法返回的对象,放到IOC 容器
// 把配置文件的内容,映射到 new Phone 对应的 符合 javabean 规范的类上
@ConfigurationProperties(prefix = "phone")
@Bean
public Phone createPhone(){
return new Phone();
}
}
package com.yanyu.bean3;
import com.yanyu.bean3.pk1.Phone;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Bean3ApplicationTests {
@Autowired
Phone phone;
@Test
void contextLoads() {
}
@Test
void test1(){
System.out.println(phone);
}
}
问题:莫名其妙, no 一致 为 null ,no 改 id 就没事
2. 检查字段类型是否正确
确保配置文件中的属性值类型与字段类型匹配。如果字段类型是 Integer
,配置文件中的值必须是一个整数;如果字段类型是 String
,配置文件中的值必须是一个字符串。
示例
如果字段类型是 Integer
,配置文件中的值必须是整数:
yaml复制
myapp:
port: 8080 # 必须是整数
如果配置文件中的值是字符串(例如,port: "8080"
),Spring 会尝试将其转换为 Integer
,但如果值是无效的(例如,port: "abc"
),字段将为 null
。