概述
spring中的bean如果实现了Aware相关的接口,容器会为它自动注入ApplicationContext,Environment这些spring内置的组件。
那spring是如何自动注入这些组件的?
spring中获取bean的流程
spring的容器预留了BeanPostProcessor的扩展点,该接口的实现类,会在bean初始化前后,对bean进行处理。处理流程如下:
Aware功能的实现
从上述流程中可以看到,我们可以实现特定的BeanPostProcessor,来为bean实现Aware功能。
翻阅spring的源码可以看到:
- AbstractApplicationContext的refresh函数。
从FileSystemXmlApplicationContext等cnontex的具体实现类的初始化函数,可以一层层跟踪到这一段代码。
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
# 后面代码已省略
}
- prepareBeanFactory方法
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.setBeanClassLoader(this.getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
# 重点
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
# 代码有省略
- 下面是ApplicationContextAwareProcessor的实现,可以看到其实现了BeanPostProcessor 接口
而且springcontex在初始化的过程中注册了该组件。所以bean实例化后,会经过ApplicationContextAwareProcessor的处理。 可以看到其为相关的Aware接口进行回调,并将特定的组件注入到bean中。
注:低层次的API,比如XMLFactoryBean是不具备Aware功能的,因为它没有注册相关的BeanPostProcessor 。
这也是为啥spring官网推荐使用contex而不是beanfactory。
beanfactory只是实现了初级的容器功能,spring的很多功能比如Aware,切面等都是通过BeanPostProcessor 来实现的。
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
}
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
this.invokeAwareInterfaces(bean);
return bean;
}
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 ApplicationContextAware) {
((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
}
}
}