Spring Aware接口执行时机源码深度解读
Spring中有这样一种标记接口的存在Aware,只要是spring管理的bean实现了Aware接口,那么spring就会在bean创建的某个时机将相应的资源注入到该spring bean中,比如ApplicationContextAware, 会将spring 应用上下文ApplicationContext自动注入到bean中。
//Spring Aware标记接口
public interface Aware {
}
Spring内建的Aware接口
Spring 内建的Aware大概分为以下几种
Spring core 和 context的内建Aware接口
- ApplicationEventPublisherAware
- MessageSourceAware
- ResourceLoaderAware
- BeanFactoryAware
- EnvironmentAware
- EmbeddedValueResolverAware
- ImportAware
- LoadTimeWeaverAware
- BeanClassLoaderAware
- BeanNameAware
- ApplicationContextAware
Spring web内建的Aware接口
- ServletContextAware
- ServletConfigAware
Spring其它内建Aware接口
- SchedulerContextAware (spring scheduling)
- NotificationPublisherAware (spring jmx export)
- BootstrapContextAware (spring jca)
如此多的Aware接口,还不包含定制以及第三方引用的(关于如何定制自己的Aware接口不在此探讨,会专门拿出一章来深究), 那么它们的执行时机和顺序是怎样的呢?在我们使用到多个Aware接口而且还需要注意其执行时机和顺序的时候,就必须要弄清楚这一块的逻辑。接下来就是本文重点,深入spring源码来考证探究其原理及发现总结其执行时机以及执行顺序的结论。
Spring内建Aware接口的执行时机及顺序
我们可以猜想到Aware接口的执行时机肯定是在Spring Bean创建的时候,那究竟具体在哪呢?接下来一起来探究一下。
纵观Spring,对于Aware接口的执行实现主要有一下两种模式
- 初始化Bean的时候直接进行方法调用 -> setXXXX
- BeanPostProcessor -> Object postProcessBeforeInitialization(Object bean, String beanName)
结论:直接方法调用的时机要早于通过BeanPostProcessor#postProcessBeforeInitialization调用的时机
接下来分析一下:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
由以上代码片段可以看出,在Spring初始化bean的阶段,首先是先调用执行invokeAwareMethods(beanName, bean)
, 然后再执行BeanPostProcessor#postProcessBeforeInitialization
, 因此Aware接口执行顺序是 直接方法调用 > 通过BeanPostProcessor#postProcessBeforeInitialization执行调用
。
下面来具体分析一下具体Aware接口的调用执行顺序。
直接方法调用 -> invokeAwareMethods(beanName, bean)
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {