开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第30天,点击查看活动详情
IOC资源管理
jdk原生的资源加载方式是用ClassLoader中的getResource方法和getResourceAsStream方法。Spring没有用jdk原生的资源管理方法,而是自己重新打造了一套。
原生jdk的url那一套资源加载方式,对于classpath或ServletContext中的资源来说没有标注的处理手段。别人的不足也是Spring大哥的优势。
java原生加载方式
java原生加载方式可以加载到下述资源:
- 借助ClassLoader加载类路径下的资源(classpath)
- 借助File加载文件系统的资源
- 借助URL和不同的协议加载本地/网络上的资源
spring基于三种加载方式做了实现,并且新增了从ServletContext 域获取资源。
本文另一个较为重要的点是@PropertySource,看到这个注解很容易联想到properties资源的加载。
@PropertySource引入properties文件
我们拿jdbc的连接举例来说明: 新建一个jdbc的properties文件如下,并放到resource下:
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.driver-class-name=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=123456
接着编写配置类;
@Configuration
@ComponentScan("com.lyz.spring21")
@PropertySource("spring21/jdbc.properties")
public class JdbcPropertiesConfiguration {
}
编写资源配置模型类:
@Component
public class JdbcProperties {
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.driver-class-name}")
private String driverClassName;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Override
public String toString() {
return "JdbcProperties{" +
"url='" + url + ''' +
", driverClassName='" + driverClassName + ''' +
", username='" + username + ''' +
", password='" + password + ''' +
'}';
}
#get和set省略......
}
最后写我们的启动类:
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx= new AnnotationConfigApplicationContext(JdbcPropertiesConfiguration.class);
System.out.println(ctx.getBean(JdbcProperties.class).toString());
}
}
该示例运行结果如下;
这这基本操作大家应该耳熟能详了吧。
需要注意的一点是在配置类上我们是用来@PropertiesSource这个注解将我们的properties资源导入到spring,然后借助@Value注解为模型属性赋值。
其实PropertiesSource不仅能解析properties资源文件,也可以解析xml,只是我们编写这个xml需要严格根据格式来写才能解析,用的不多就不去深入讲解了。
PropertiseSource借助snake-yaml读取yml/yaml资源文件
上述properties写成yml文件的话就变成了下面这样(声明yml文件)
yml:
jdbc:
url: jdbc:mysql://localhost:3306/test
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
程序的改动在@Value处,每个jdbc.xxx要加个yml前缀。 最后的输出结果:
JdbcYmlProperty{url='${yml.jdbc.url}', driverClassName='${yml.jdbc.driver-class-name}', username='${yml.jdbc.username}', password='${yml.jdbc.password}'}
啊这,什么也没读出来,说明它是无法直接解析yml的。通常我们是借助snake-yaml来解析yml资源。 首先导入依赖;
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.26</version>
</dependency>
定义YmlSourceFactory类实现PropertySourceFactory接口。
第三步是把这个 YmlPropertySourceFactory 设置到 @PropertySource 中:
@PropertySource(value = "classpath:propertysource/jdbc.yml", factory = YmlPropertySourceFactory.class)
第四步借助snake-yaml将资源文件转换为Properties对象:
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
// 传入resource资源文件
yamlPropertiesFactoryBean.setResources(resource.getResource());
// 直接解析获得Properties对象
Properties properties = yamlPropertiesFactoryBean.getObject();
// 如果@PropertySource没有指定name,则使用资源文件的文件名
return new PropertiesPropertySource((name != null ? name : resource.getResource().getFilename()), properties);
}
再进行测试解析出来了:
JdbcYmlProperty{url='jdbc:mysql://localhost:3306/test', driverClassName='com.mysql.jdbc.Driver', username='root', password='123456'}
上述就是本文讲的内容了,也是一些个人理解,有理解不正确的地方还请小伙伴们进行指正。