無論是咱們平時開發中,仍是在看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
接口