Spring Boot中的Binder类基本使用和工具封装
参考网址:
工具类: 配置文件和实体类之间的映射
Spring Boot中的Binder类
Spring Boot2.x Binder
- 一、问题描述
- 二、简单示例
- 三、常用方法
- bind方法:将配置文件中的属性值绑定到Java对象中。
- bindOrCreate方法:如果Java对象不存在,则创建一个新的对象并将配置文件中的属性值绑定到该对象中。
- bindProperty方法:将配置文件中的单个属性值绑定到Java对象的属性中。
- bindAnnotations方法:将Java对象中带有@ConfigurationProperties注解的属性绑定到配置文件中的属性值。
- 四、工具方法
一、问题描述
- 在基于springboot进行封装自定义框架或对某个开源框架进行二次改造时我们经常会涉及到将application.yml或者application.properties中配置的属性绑定到某个类对应的属性上
- 使用 @Value 或 @ConfigurationProperties这种方式就不多说了,使用比较简单,但是局限性也比较大,比如只能在容器启动过程中的特定阶段进行绑定,如果容器启动好了或者容器正常运行中,再想去将动态读取到的配置属性绑定到某个对象上,那么 @Value 或 @ConfigurationProperties 是做不到的
- 比如:监听到配置中心配置发生变更,此时我们需要将变更的配置绑定到某个对象上(或者替换environment对象里的某个属性值)
- 比如:在容器启动过程中(配置属性还没有绑定到@Value或@ConfigurationProperties标识的类上),此时我们需要将properties配置文件里的某些属性读取出来(映射到某个对象上)
- 比如:【多数据源组件开发】在spring启动过程中利用【BeanDefinitionRegistry + 动态读取配置文件配置的多个数据源配置】来动态的向容器里注册自定义数据源的bean定义信息,以便spring启动时能将这些自定义的数据源注入容器
在人家封装之前看简单示例
二、简单示例
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.core.env.Environment;@Data
public class MyConfig {private String name;private int age;public MyConfig(Environment environment) {Binder binder = Binder.get(environment);this.name = binder.bind("myconfig.name", String.class).orElse("lucifer");this.age = binder.bind("myconfig.age", Integer.class).orElse(25);}
}
使用Binder类将配置文件中的属性值绑定到这些属性中。在构造函数中,首先获取了一个Binder实例,然后使用bind方法将配置文件中的属性值绑定到Java对象中。如果属性不存在,则使用默认值。
配置文件中属性:
myconfig.name=ron
myconfig.age=25
需要将Environment对象传递给MyConfig的构造函数,以便Binder类可以访问配置文件中的属性值。在Spring Boot应用程序中,可以通过@Autowired注解将Environment对象注入到MyConfig类中。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;@Configuration
public class AppConfig {@Autowiredprivate Environment environment;public MyConfig myConfig() {return new MyConfig(environment);}
}
三、常用方法
bind方法:将配置文件中的属性值绑定到Java对象中。
@ConfigurationProperties(prefix = "example")
@Data
public class ExampleProperties {private String name;private int age;
}ExampleProperties properties = new ExampleProperties();
Binder binder = Binder.get(environment);
// Bindable.ofInstance() 和 Bindable.of()
// 一个是实例对象,一个是实体类
binder.bind("example", Bindable.ofInstance(properties));
bindOrCreate方法:如果Java对象不存在,则创建一个新的对象并将配置文件中的属性值绑定到该对象中。
ExampleProperties properties = Binder.get(environment).bindOrCreate("example", Bindable.of(ExampleProperties.class));
bindProperty方法:将配置文件中的单个属性值绑定到Java对象的属性中。
ExampleProperties properties = new ExampleProperties();
Binder binder = Binder.get(environment);
binder.bindProperty("example.name", Bindable.ofInstance(properties), String.class);
bindAnnotations方法:将Java对象中带有@ConfigurationProperties注解的属性绑定到配置文件中的属性值。
@Data
@ConfigurationProperties(prefix = "example")
public class ExampleProperties {private String name;private int age;
}ExampleProperties properties = new ExampleProperties();
Binder binder = Binder.get(environment);
binder.bindAnnotations(properties);
四、工具方法
所以我们需要一个灵活的配置属性 <—> Java对象的映射工具类,在springboot2.x中提供了非常方便的org.springframework.boot.context.properties.bind.Binder
来进行绑定
/*** <p>* springboot2.x提供的属性绑定器* </p>** @author wenpan 2022/12/10 1:34 下午*/
public class PropertiesBinder2X {private PropertiesBinder2X() {}/*** <p>* 从 Map类型的properties 中按照prefix查找属性值并绑定到targetObj对象的对应属性上* properties 可以是自己从配置文件中读取的key-value键值对* </p>** @param properties map* @param prefix 前缀* @param targetObj 目标对象* @author wenpan 2022/12/10 1:33 下午*/public static <T> void bindDtpProperties(Map<?, Object> properties, String prefix, T targetObj) {ConfigurationPropertySource sources = new MapConfigurationPropertySource(properties);Binder binder = new Binder(sources);ResolvableType type = ResolvableType.forClass(targetObj.getClass());Bindable<?> target = Bindable.of(type).withExistingValue(targetObj);binder.bind(prefix, target);}/*** <p>* 从environment中按照prefix查找属性值并绑定到targetObj对象的对应属性上* </p>** @param environment environment* @param prefix 前缀* @param targetObj 目标对象* @author wenpan 2022/12/10 1:32 下午*/public static <T> void bindDtpProperties(Environment environment, String prefix, T targetObj) {Binder binder = Binder.get(environment);ResolvableType type = ResolvableType.forClass(targetObj.getClass());Bindable<?> target = Bindable.of(type).withExistingValue(targetObj);binder.bind(prefix, target);}
}