无论是咱们平时开发中,仍是在看spring源码中,都会遇到Aware这个接口,Aware的英文意思:意识到,察觉到,发觉,发现。从英文翻译来看,Aware作的事情应该是发现某一个东西。java
注释的大体意思是:Aware是一个标记性的超接口(顶级接口),指示了一个Bean有资格经过回调方法的形式获取Spring容器底层组件。实际回调方法被定义在每个子接口中,并且一般一个子接口只包含一个接口一个参数而且返回值为void的方法。spring
说白了:只要实现了Aware子接口的Bean都能获取到一个Spring底层组件。markdown
自定义组件时,想要使用spring容器底层的一些组件,好比ApplicationContext、Beanfactory,xxx等,只须要让自定义组件实现xxxAware,在对象实例化的时候,会把spring底层的一些组件注入到自定义的bean中。经过查看源码,能够看到有这么多的接口,每一个接口都有都对应spring相应的底层,好比:app
这里就以一些经常使用的接口进行举例,实现其接口,经过这些接口使用spring底层的一些组件post
// 启动类
@Test
public void TestMain() {
// 建立IOC容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
}
// 待注入的bean
@Component
public class User implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
private ApplicationContext applicationContext;
// 经过上下文环境对象获得Spring容器中的Bean
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("传入的IOC:" + applicationContext);
this.applicationContext = applicationContext;
}
// 获取bean的名字
public void setBeanName(String s) {
System.out.println("当前bean的名字:" + s);
}
// 解析一些字符串、占位符等
public void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {
String resolveStringValue = stringValueResolver.resolveStringValue("你好${os.name}");
System.out.println("解析的字符串是:" + resolveStringValue);
}
}
// 配置类
@Configuration
public class AppConfig {
@Bean
public User User(){
return new User();
}
}
复制代码
运行启动类,能够看到输出结果以下:this
这里对Aware的三个接口进行了举例,分别是ApplicationContextAware、BeanNameAware、EmbeddedValueResolverAwarespa
- ApplicationContextAware:经过上下文环境对象获得Spring容器中的Bean
- BeanNameAware:获取bean的名字
- EmbeddedValueResolverAware:解析一些字符串、占位符等
其实每个子接口,都是利用相应的xxxProcess
来进行处理的,也就是相应的后置处理器,而这些xxxProcess
都是BeanPostProcess
的接口,好比ApplicationContextAware
就是经过ApplicationContextAwareProcess
来进行处理的,ApplicationContextAwareProcess
实现了BeanPostProcess
翻译
这里就以ApplicationContextAware
,经过Debug调试进行源码追踪,看看是如何给User把ApplicationContext给注入进来的:调试
在setApplicationContext方法进行断点调试:code
经过方法调用栈,能够看到ApplicationContextAwareProcessor
调用postProcessBeforeInitialization
方法,
- 判断是不是xxxAware接口,判断是,则继续往下
- 经过invokeAwareInterfaces里面进行注入
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 判断是不是xxxAware接口,判断是,则继续往下
if (!(bean instanceof EnvironmentAware) && !(bean instanceof EmbeddedValueResolverAware) && !(bean instanceof ResourceLoaderAware) && !(bean instanceof ApplicationEventPublisherAware) && !(bean instanceof MessageSourceAware) && !(bean instanceof ApplicationContextAware) && !(bean instanceof ApplicationStartupAware)) {
return bean;
} else {
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(() -> {
this.invokeAwareInterfaces(bean);
return null;
}, acc);
} else {
// 在这个方法进行相应的注入
this.invokeAwareInterfaces(bean);
}
return bean;
}
}
复制代码
点开invokeAwareInterfaces方法,这个bean参数就是User对象,将须要注入的bean传入,作以下处理:
这里以ApplicationContextAware为例,实现了ApplicationContextAware接口,则将User对象转成ApplicationContextAware接口调用setApplicationContext方法进行注入
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware)bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware)bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware)bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationStartupAware) {
((ApplicationStartupAware)bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
}
}
复制代码
xxxProcess
后置处理器判断这个bean是不是xxxAware
接口