ApplicationContextAware接口
public interface ApplicationContextAware extends Aware {
/**
* ApplicationContextAware 接口定义了一个抽象方法
*/
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
何时被调用?
就是在执行bean初始化的方法中被调用的
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
/**
* 当这个后置处理器被调用的时候,会走下面的if条件,就是看看你当前正在创建的bean有没有实现以下这些接口
* 若没有实现以下这些接口则直接返回该bean
*/
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
return bean;
}
/**
* 代码能继续向下走,说明当前bean实现了以上接口至少一个
*/
//我自己写得Person.java类就实现了其中得ApplicationContextAware方法
//执行以上接口(EnvironmentAware\EmbeddedValueResolverAware\ResourceLoaderAware。。。就是上面if中的几个接口)的回调
invokeAwareInterfaces(bean);
}
return bean;
}
/**
* 判断当前bean实现了哪个Aware接口,然后进行强制类型转换成父类,因为invokeAwareInterfaces()方法传入的是Object类型的,所以要强转
* 之后调用对象的方法执行aware回调
* **/
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);//会把当前bean工厂传入进去
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);//会把当前bean工厂传入进去
}
if (bean instanceof MessageSourceAware) {//利用多态的特性给Person类中的MessageSource赋值
((MessageSourceAware) bean).setMessageSource(this.applicationContext);//会把当前bean工厂传入进去
}
/**
* 我是用过的最典型的就是这个ApplicationContextAware了
* 就是当前bean实现了ApplicationContextAware接口,那么此时就会调用当前bean重写的setApplicationContext方法
* 并将applicationContext对象传进去,我们知道applicationContext中包含了BeanFactory对象,
* 也就是applicationContext中有BeanFactory属性,那我们只要能把applicationContext对象注入给当前bean的属性,那么当前bean就可以操作bean容器了
*/
if (bean instanceof ApplicationContextAware) {//this.applicationContext:获取的是高级容器 然后调用getBeanFactory()方法获取底层DefaultListableBeanFactory容器
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
案例
@Component
public class UserService implements ApplicationContextAware {
/**
* 实现ApplicationContextAware接口,当spring在创建UserService这个bean对象的时候
* 执行initializeBean(初始化bean)的时候会回调setApplicationContext()方法,此时会把bean工厂传进来
*/
private static ApplicationContext applicationIocContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
applicationIocContext=Optional.ofNullable(applicationIocContext).orElse(applicationContext);
}