述
上文中,介绍了几种 Spring Boot 中的属性配置方式,那么配置完成之后,要在系统里面怎么获取,下面来介绍一种通过 Spring Aware
获取属性的方式
获取属性
这里利用之前学过的启动加载器去打印要获取的属性, 这里还是创建一个类 EnvironmentApplicationRunner
然后去实现 ApplicationRunner
,然后再去实现一个 EnvironmentAware
用来获取 Environment
对象,代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16@Component
@Slf4j
public class EnvironmentApplicationRunner implements ApplicationRunner, EnvironmentAware {
private Environment environment;
@Override
public void run(ApplicationArguments args) throws Exception {
log.info(environment.getProperty("environment.test"));
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
}
之后运行,日志打印1
2020-02-14 15:15:44.427 INFO 32056 --- [ main] c.z.s.e.s.EnvironmentApplicationRunner : 30
这里已经成功获取到系统配置的属性了
Spring Aware
在 Spring 框架中,Bean 是感知不到容器的存在的,当我们需要使用 Spring 容器的一些功能或者资源的时候,就需要用到 Spring Aware
来实现, 比如我们上面用的 EnvironmentAware
就可以用来获取 Environment
对象
常用的 Spring Aware
Spirng 提供了一些常用的 Aware, 如下:
类名 | 作用 |
---|---|
BeanNameAware | 获取容器中的Bean名称 |
BeanClassLoaderAware | 获得类加载器 |
BeanFactoryAware | 获得BeanFactory |
EnvironmentAware | 获取环境变量 |
EmbeddedValueResolverAware | 获取容器加载的 properties 文件属性值 |
ResourceLoaderAware | 获取资源加载器 |
ApplicationEventPublisherAware | 获取系统广播器 |
MessageSourceAware | 获得文本信息 |
ApplicationContextAware | 获得当前应用上下文 |
原理解析
为什么被Spring管理的类,只要实现了Aware接口,Spring就会自动把对应的对象注入进来,带着这个问题,我们来看一下源码.
首先,从我们熟悉的 refresh()
方法入手, 这里面的 prepareBeanFactory()
方法,这个方法具体的作用我们之前有写,这里就只看关于 Aware 的一些代码,如下:
对于 BeanPostProcessor
我们已经很熟悉了,然后我们进入这个类,看一下他里面的方法
然后再看一下这里调用的 invokeAwareInterface()
这个方法
这个类中,会处理一部分的 Aware ,那么这个方法是什么时机被调用的,在 doCreateBean()
这个方法后面会调用 initializeBean()
这个方法,进入看一下:
这里有先是一个 Aware 相关的方法 invokeAwareMethods()
,进去看一下
这个方法中,会处理一部分的 Aware , 然后就是 applyBeanPostProcessorsBeforeInitialization()
这个方法,进入看一下
这里就会执行 prepareBeanFactory()
方法中添加的那个 ApplicationContextAwareProcessor
,处理其他的 Aware
Spring Aware 的加载流程大概就是这样
自定义Spring Aware
了解了 Spring Aware 的实现原理,之后,我们可以自定义一个 Spring Aware, 首先仿照上面用到的 EnvironmentAware
,新建一个 MySpringAware
继承 Aware
接口, 代码如下:1
2
3
4
5public interface MySpringAware extends Aware {
void setAwareModel(AwareModel awareModel);
}
然后这里用到的 AwareModel
代码如下:1
2
3
4
5
6
7@Component
@Data
public class AwareModel {
private String name = "defaultName";
}
然后我们需要一个 BeanPostProcessor
对应源码中的 ApplicationContextAwareProcessor
,代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18@Component
public class MyAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
public MyAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof MySpringAware) {
((MySpringAware) bean).setAwareModel((AwareModel) applicationContext.getBean("awareModel"));
}
return bean;
}
}
最后在我们开始的那个启动加载器里,实现我们自定义的 Aware 来测试一下是否生效1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24@Component
@Slf4j
public class EnvironmentApplicationRunner implements ApplicationRunner, EnvironmentAware, MySpringAware {
private Environment environment;
private AwareModel awareModel;
@Override
public void run(ApplicationArguments args) throws Exception {
log.info(environment.getProperty("environment.test"));
log.info(awareModel.getName());
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public void setAwareModel(AwareModel awareModel) {
this.awareModel = awareModel;
}
}
启动,日志输出如下:1
22020-02-14 17:17:38.894 INFO 22756 --- [ main] c.z.s.e.s.EnvironmentApplicationRunner : 34
2020-02-14 17:17:38.894 INFO 22756 --- [ main] c.z.s.e.s.EnvironmentApplicationRunner : defaultName
总结
了解Spring Aware的用法,还有一些常用的 Spring Aware, 以及他们的工作原理,源码部分也比较简单
Aware加载流程图如下:
自定义Aware流程图如下: