SpringBoot 如何在静态方法中读取配置文件的值
在Spring中呢有很多读取配置文件值的相关注解,读取这些配置文件都是依赖于Spring的方式。我发现的读取配置文件的方式有好几种。
1、@Value 注解
2、@ConfigurationProperties 和 @EnableConfigurationProperties(@Compent)
3、@PropertySource
4、Environment
5、PropertySourcesPlaceholderConfigurer
6、自己写一个静态读取的配置文件的工具类(包括 jar 包外的配置文件,与SpringBoot读取的配置文件一致)
配置好一个配置文件
users: name: yj sex: 男 age: 23
写一个测试类
@SpringBootApplication(exclude ={ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})public class App{ public static void main( String[] args ) { System.out.println( "Hello World!" ); ConfigurableApplicationContext context = SpringApplication.run(App.class, args); context.getBean(UserService.class).outValue(); }}@Componentclass UserService{ @Value("${users.name}") private String userName; public void outValue(){ System.out.println(userName); }}
1、@Value 注解 读取
@Value 注解的读取配置文件是依赖于IOC容器的,也属于依赖注入,这一点看过Spring的IOC源码的都清楚,属于属性的注入,所以是依赖于Spring的,所以呢,在该类使用@Value注解的时候,该类必须是归属于Spring管理的类。
示例:
@Componentclass UserService{ @Value("${users.name}") private String userName; public void outValue(){ System.out.println(userName); }
}
2、@ConfigurationProperties 和 @EnableConfigurationProperties
@ConfigurationProperties 注解适用于自动化配置的类,在SpringBoot的jdbc的数据源自动化配置:
@ConfigurationProperties(prefix = "spring.datasource")public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean { private ClassLoader classLoader; private String name; private boolean generateUniqueName; private Class extends DataSource> type; private String driverClassName; private String url; private String username; private String password; private String jndiName; private DataSourceInitializationMode initializationMode; private String platform; private List<String> schema; private String schemaUsername; private String schemaPassword; private List<String> data; private String dataUsername; private String dataPassword; private boolean continueOnError; private String separator; private Charset sqlScriptEncoding; private EmbeddedDatabaseConnection embeddedDatabaseConnection; private DataSourceProperties.Xa xa; private String uniqueName; // ............
}
在SpringBoot中我们使用数据源是这样子配置的:
# 数据源
spring: #数据源datasource: url: jdbc:mysql://www.memoryoverflow.cn:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true username: root password: 12345
driver-class-name: com.mysql.jdbc.Driver
所以在我们也需要写一个自动化配置类的时候,就可以使用改注解来处理。
有个地方需要注意的地方
类似于这样有行杠的,在java类中需要与驼峰的方式命名。
driver-class-name ----> driverClassName
示例:配置文件在上面已经写了
@ConfigurationProperties(prefix = "users")public class User{ private String name; private String sex; private String age; // 省略 get set ,实际代码中不可省略 set方法,否则无法注入 @Override public String toString() { return "User{" + "name='" + name + '\'' + ", sex='" + sex + '\'' + ", age='" + age + '\'' + '}'; }}
在启动类中加入 注解 @EnableConfigurationProperties(value={User.class})
或者在 User.class 加上 @Compent 注解
@EnableConfigurationProperties(value={User.class})@SpringBootApplication(exclude ={ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})public class App{ public static void main( String[] args ) { System.out.println( "Hello World!" ); ConfigurableApplicationContext context = SpringApplication.run(App.class, args); context.getBean(UserService.class).outValue(); // 打印出User对象 System.out.println(context.getBean(User.class)); }}
3、@PropertySource 和 @Configuration
@PropertySource 指定加载配置文件,但是不支持yml 的配置方式,也不支持打jar包后读取jar包外的配置,只能是类路径下的,不友好。也是依赖Spring的所以使用改注解的类需要放到Spring的IOC管理
示例:
配置
config.app=TestAppconfig.version=1.0.0
配置类:
@Component@PropertySource(value = "classpath:config.properties")@ConfigurationProperties(prefix = "config")public class AppConfig{ private String app; private String version; @Override public String toString() { return "AppConfig{" + "app='" + app + '\'' + ", version='" + version + '\'' + '}'; } // 省略set}
4、Environment
在Spring里可以通过注入 该对象,就可以读取配置文件的的属性值,也是依赖于Spring的注入
获得改对像的方式有好多方式:介绍两种
@Autowired依赖注入
@AutowiredEnvironment environment
实现接口EnvironmentAware。当一个工具类使用,但是该工具类得需要在Spring容器启动后,才可以使用
@Componentclass MyEnvironmentAware implements EnvironmentAware{ private static Environment environment; public static String getProperties(String key) { if (environment == null) { throw new RuntimeException("Environment 对象尚未初始化"); } return environment.getProperty(key); } @Override public void setEnvironment(Environment env) { environment = env; System.out.println(environment.getProperty("users.name")); }}
5、 PropertySourcesPlaceholderConfigurer
PropertySourcesPlaceholderConfigurer是个bean工厂后置处理器的实现,同时也实现了 EnvironmentAware,也是处理 @Value 属性注入的处理关键类。该类的属性也是来自 Environment 的。
示例:
@Componentclass MyPropertySourcesPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer{ private static PropertyResolver propertyResolver; public static String getValue(String key){ if (propertyResolver==null){ throw new RuntimeException("PropertyResolver 尚未初始化"); } return propertyResolver.getProperty(key); } @Override protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, ConfigurablePropertyResolver pr) throws BeansException { super.processProperties(beanFactoryToProcess, pr); propertyResolver=pr; }}
6、自己写一个静态读取的配置文件的工具类(包括 jar 包外的配置文件,与SpringBoot读取的配置文件一致
在上面读取配置文件的方式中有几个点:
1、这些文件的方式都依赖Spring的注入。
2、静态方式读取不方便,必须得在Spring容器启动才可以加载配置文件,对于有时需要在Spring容器启动完毕前,需要加载配置文件不方便。
3、自定义加载配置问题,不可以加载jar包外的自定义配置文件。除了:application.yml/ properties和 不同环境的配置文件外。比如 @PropertySource 注解只能加载 类路径下的。打jar包后不可以使用,切不能加载y ml配置。
结合以上几点,我们可以自己写一个 在Spring的读取配置的基础上,补全以上问题的工具类。
1、工具类的功能介绍:
如果在启动项目的时候,通过参数指定配置文件的方式的时候。该工具类不会加载该参数指定的其它配置文件。文件的读取规则如下。
基于SpringBoot 使用
工具类加载配置文件的顺序与SpringBoot保持一致
配置文件有先级:. properties> .yml ;优先加载. properties 如果没有就加载 yml的
开发环境下:resources/config > resources/
jar包:jar包同级目录的config/ > jar包同级目录 > jar 包内的resources/config/ jar 包内的resources/
默认加载:application.properties、application.properties的spring.profiles.active 指定的文件、和一个config.propertis/config.yml(优先于config.propertis);
上一点的三个默认配置文件可以在jar包同级目录config文件夹下或者jar包同级目录下。方便于修改,于SpringBoot加载顺序一样。
加载 list集合方式:
例如:
# ymllists: [1,2,3,4] lists: 1,2,3,4# propertieslists=[1,2,3,4]lists=1,2,3,4
# ymllists: - 1 - 2 - 3
map 结构方式读取
例如:
不支持对象嵌套对象。
# ymlmap: {name:tom,age:18}#propertiesmap={name: tom , age:18 }
不支持 集合对象方式读取
不支持这样子配置的集合读取:
关于改工具类的集合和map的配置:
集合和map的读取方式,需要按照如上说明配置。
如果不使用该工具类读取集合和map结构,但是需要注入到类对象中的话,可以按照SpringBoot中的配置规则去配置。
也可以配置成集合对象,当字符串读取,然后自己转换。
2、工具类的使用(两种)
1、可以将工具打成一个 jar 包/将该源码,引入到项目中,然后在启动类加上注解 @EnableReadConfig
该方式需要依赖于Spring的方式,可以读取系统变量,需要等待Spring启动,加载。
2、手工加载
该方式目前不可读取系统变量,但是可以不依赖Spring容器去加载。
// 参数 类加载器 :引用该类的任意类class PropertiesUtils.load(DemoApplication.class)
3、加载第三方配置文件
void load(String... path) // 例如:PropertiesUtils.load("classpath:app.yml","/Users/yongjian/work/server/jar-base/demo/src/main/java/com/example/demo/a.yml");
加了 classpath:代表加载的是类路径下的。其它的就是 绝对路径下的配置文件
示例:
@SpringBootApplication@EnableReadConfig(classLoader = DemoApplication.class)public class DemoApplication{ public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); PropertiesUtils.load("classpath:app.yml","/Users/yongjian/work/server/jar-base/demo/src/main/java/com/example/demo/a.yml"); System.out.println(); System.out.println("a.yml:" + PropertiesUtils.getStringValue("spring.profiles.active")); System.out.println("app.yml:" + PropertiesUtils.getStringValue("name")); System.out.println("系统资源:" + PropertiesUtils.getStringValue("user.dir")); System.out.println("application-dev.properties:" + PropertiesUtils.getMap("map")); System.out.println("config.properties:" + PropertiesUtils.getMap("mapp")); System.out.println("绝对路径:" + PropertiesUtils.getList("lists")); }}
打印结果:
jar包方式:
开发环境方式:
3、代码结构
PropertiesUtils.java工具类api
该工具类的地址:https://gitee.com/lyj08/tools-read-config