基于注解实现springboot支持自定义yaml配置载入

基于注解实现springboot支持自定义yaml配置载入

一、前置知识

阅读本篇文章时,具备以下知识会更便于理解:

  • java中注解类的定义以及使用
  • java反射的使用
  • spring中bean的初始化流程

二、背景

@PropertySource注解支持引入自己创建的配置文件,但是在spring新版本中仅支持.properties格式的配置文件。
总所周知,properties配置文件在遇到自定义的复杂对象属性时,阅读性差的跟个鬼一样。而yaml格式的配置文件就很好的解决了这一问题。
国内技术博客现状,ctrl c + v,懂我意思吧。找不到通用性高的就自己手搓。

三、开整

1. 首先定义一个注解@YamlSource

@PropertySource用法保持一致,放在配置类上

/**
 * @author tomshidi
 * @date 
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface YamlSource {
    /**
     * yaml配置文件路径
     * @return 路径
     */
    String path();

    /**
     * 字符编码,默认UTF-8,暂未实现
     * @see StandardCharsets#UTF_8 etc.
     * @return 字符编码
     */
    String encoding() default "UTF-8";
}

2. 定义一个bean实例化处理器类

每一步的作用已经写在注释中了,如果看不懂,不要私信我,先看文档开始的那些知识点是不是都熟练运用了。

/**
 * @author tomshidi
 * @date 
 */
@Component
public class ThirdPartYamlProcessor implements InstantiationAwareBeanPostProcessor, ApplicationContextAware {

    /**
     * spring环境上下文,用来获取环境参数存储对象
     */
    private ApplicationContext applicationContext;

    /**
     * ApplicationContextAware接口中方法的实现,由spring框架在注册当前bean时自动执行
     * @param applicationContext spring环境上下文
     * @throws BeansException 异常
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * bean实例化前置处理方法,spring中每一个bean初始化都会走到这个方法
     * 当然,我们自定义的bean也会进这里,这也就是我们的目的
     *
     * @param beanClass bean对象Class
     * @param beanName  bean的名字
     * @return
     * @throws BeansException 异常
     */
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        // 获取配置类上的@YamlSource注解
        YamlSource yamlSource = beanClass.getAnnotation(YamlSource.class);
        // 如果没找到,跳过后续逻辑
        if (yamlSource == null) {
            return null;
        }
        // 这个对象是用来解析yaml文件的
        YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
        // 将@YamlSource注解中path参数指定的文件当做资源载入
        yamlPropertiesFactoryBean.setResources(new ClassPathResource(yamlSource.path()));
        // 获取yaml文件解析的数据
        Properties properties = yamlPropertiesFactoryBean.getObject();
        // 获取spring的环境参数对象,也就是各种配置的大集合。
        Environment environment = applicationContext.getEnvironment();
        ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) environment;
        MutablePropertySources propertySources = configurableEnvironment.getPropertySources();
        // 将我们自定义的yaml文件中的配置写入到spring环境参数中
        // 这样在后面配置类bean属性赋值时,spring就能找到对应的值
        propertySources.addFirst(new PropertiesPropertySource("defaultProperties", properties));
        return null;
    }
}

3. 编写自定义yaml配置文件third-part.yml

放在resources/config/third-part.yml这个路径,当然,这个路径与@PropertySource中路径的使用方法保持一致。
这里定义了基础的String,Integer类型,还定义了一个List对象。

third:
  name: tomshidi
  age: 1000
  nick-name:
    - tom
    - shi
    - di

4. 定义一个配置类ThirdPartConfig

上面忙活了半天,现在来测试一下我们的注解好不好用。

/**
 * @author tomshidi
 * @date 
 */
@Component
@YamlSource(path = "config/third-part.yml")
@ConfigurationProperties(prefix = "third")
public class ThirdPartConfig {
    private String name;

    private Integer age;

    private List<String> nickName;

    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;
    }

    public List<String> getNickName() {
        return nickName;
    }

    public void setNickName(List<String> nickName) {
        this.nickName = nickName;
    }

    @Override
    public String toString() {
        return "ThirdPartConfig{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", nickName=" + nickName +
                '}';
    }
}

5. 启动类

启动类中不需要任何操作,这里为便于查看结果,就手动获取配置类bean对象了。

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);
        ThirdPartConfig thirdPartConfig = applicationContext.getBean(ThirdPartConfig.class);
        System.out.println(thirdPartConfig.toString());
    }
}

6. 效果图

效果自然是非常奈斯
基于注解实现springboot支持自定义yaml配置载入


最后,禁止转载。

上一篇:1074. Number of Submatrices That Sum to Target (H)


下一篇:k8s-dashboard ui部署