Spring Aware接口执行时机源码深度解读

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) {
   
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值