spring ApplicationContextAware的使用和执行时机
实际项目开发中,会写类似如下的工具类,方便做脚本执行或者一些判断,提供一些api方法等(可阅读:https://blog.csdn.net/qq_26437925/article/details/114213391 ,ApplicationContextAware就大派用场了),如下
@Component
public class SpringApplicationUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringApplicationUtil.applicationContext = applicationContext;
}
public static Object getBean(String beanName){
return applicationContext.getBean(beanName);
}
public static List<String> getAllBeanNames(){
String[] arr = applicationContext.getBeanDefinitionNames();
if(arr == null || arr.length == 0){
return new ArrayList<>();
}
return Arrays.stream(arr).collect(Collectors.toList());
}
}
如下测试代码, 想拿到某个bean, 直接从这个util拿到
@Test
public void test2() throws Exception {
ApplicationContext ctx =
new AnnotationConfigApplicationContext(LocalConfig.class, LocalConfig2.class);
// 直接从工具类获取
UserService userService = (UserService)SpringApplicationUtil.getBean("userService");
Assert.assertNotNull(userService);
userService.add(new User());
((AnnotationConfigApplicationContext) ctx).close();
}
本文来探究一下它是如何工作的。
直接debug可以看到执行链路,进行具体分析
可以发现在这个bean的初始化阶段,会执行所有的BeanPostProcessor扩展的postProcessBeforeInitialization方法,会发现执行到了ApplicationContextAwareProcessor
ApplicationContextAwareProcessor怎么来的?
org.springframework.context.support.AbstractApplicationContext的refresh方法中的prepareBeanFactory(beanFactory);
执行添加的,平台内置的一个beanPostProcessor
所以回到org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization 方法中,可以看到会执行Aware接口
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(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 ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
执行ApplicationContextAware的setApplicationContext方法完成设置, 如下
其实就是AnnotationConfigApplicationContext自身,即Spring容器管理者自身。
再比如BeanAware接口, 一个Bean想知道自己的beanName,那么自己实现下BeanNameAware
public class X implements BeanNameAware {
private String xName;
@Autowired
private Y y;
public X() {
System.out.println("X()");
}
public void sy(){
System.out.println("y:" + y);
}
@Override
public void setBeanName(String name) {
this.xName = name;
}
public void sayMyName(){
System.out.println("xName:" + xName);
}