阅读本篇文章时,具备以下知识会更便于理解:
@PropertySource
注解支持引入自己创建的配置文件,但是在spring新版本中仅支持.properties
格式的配置文件。
总所周知,properties配置文件在遇到自定义的复杂对象属性时,阅读性差的跟个鬼一样。而yaml
格式的配置文件就很好的解决了这一问题。
国内技术博客现状,ctrl c + v,懂我意思吧。找不到通用性高的就自己手搓。
与@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"; }
每一步的作用已经写在注释中了,如果看不懂,不要私信我,先看文档开始的那些知识点是不是都熟练运用了。
/** * @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; } }
放在resources/config/third-part.yml这个路径,当然,这个路径与@PropertySource
中路径的使用方法保持一致。
这里定义了基础的String,Integer类型,还定义了一个List对象。
third: name: tomshidi age: 1000 nick-name: - tom - shi - di
上面忙活了半天,现在来测试一下我们的注解好不好用。
/** * @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 + '}'; } }
启动类中不需要任何操作,这里为便于查看结果,就手动获取配置类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()); } }
效果自然是非常奈斯