這個是spring-beans包中的概念欧聘,正常情況下我們使用bean是不需要考慮容器相關(guān)的特性的赐劣,所以基本在項目中不會接觸這個接口定页,但是這個接口是獲取容器相關(guān)屬性的核心迅耘,比如自己定一個一個bean,然后想在這個bean中獲取applicationContext或者beanName等屬性冤馏,那么我們就需要了解Aware接口相關(guān)的特性了日麸。我先說下源碼中如何獲取spring容器相關(guān)特性,然后再舉個例子說明下逮光。
1.spring容器啟動時會調(diào)用AbstractApplicationContext類的prepareBeanFactory方法代箭,其中會定義bean的后置處理器ApplicationContextAwareProcessor
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.setBeanClassLoader(this.getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
if (beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
if (!beanFactory.containsLocalBean("environment")) {
beanFactory.registerSingleton("environment", this.getEnvironment());
}
if (!beanFactory.containsLocalBean("systemProperties")) {
beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean("systemEnvironment")) {
beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
}
2.bean在初始化前會調(diào)用一次ApplicationContextAwareProcessor類的postProcessBeforeInitialization方法
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null && (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
ApplicationContextAwareProcessor.this.invokeAwareInterfaces(bean);
return null;
}
}, acc);
} else {
this.invokeAwareInterfaces(bean);
}
return bean;
}
3.注意postProcessBeforeInitialization方法中具體的invoke方法,如果實(shí)現(xiàn)Aware接口會繼續(xù)判斷實(shí)現(xiàn)了具體的什么接口涕刚,執(zhí)行對應(yīng)接口的方法嗡综。
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(new ApplicationContextAwareProcessor.EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
}
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 ApplicationContextAware) {
((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
}
}
}
舉個例子,MyApplicationContextAware實(shí)現(xiàn)了ApplicationContextAware接口,那么在初始化前會調(diào)用setApplicationContext方法杜漠,則可以拿到ApplicationContext
@Service
public class MyApplicationContextAware implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext(){
return applicationContext;
}
}
再舉個例子极景,可以拿到對應(yīng)bean的beanName
@Component
public class MyBeanNameAware implements BeanNameAware {
private BeanName beanName;
@Override
public void setBeanName(BeanName beanName) throws BeansException {
this.beanName = beanName;
}
public BeanName getBeanName(){
return beanName;
}
}