ApplicationContextAware底层原理详解

为什么要看ApplicationContextAware呢?

其实ApplicationContextAware只是Spring众多内容中的一小部分,如果只看它,其实对于你了解Spring整体的益处不算很大。对于大多数人而言,只要学会如何使用就足够了。那为什么还要看呢? 不得局部慢慢消化吗,所以先来个相对简单的。

ApplicationContextAware使用方式

去实现ApplicationContextAware接口,实现接口setApplicationContext 可以设置静态属性,这样我们就拿到了IOC的容器(getBean取的是一级缓存里已经创建好的Bean)

@Component
public class SpringUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(@Nullable ApplicationContext applicationContext) throws BeansException {
        if(SpringUtil.applicationContext == null) {
            SpringUtil.applicationContext = applicationContext;
        }
    }

    /**
     * 获取applicationContext
     *
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 通过name获取 Bean
     *
     * @param name
     * @return
     */
    public static Object getBean(String name){
        return getApplicationContext().getBean(name);
    }
}

底层源码

调用了重写的setApplicationContext

在这里插入图片描述根据调用的位置,我们简单过一下, 最下面一行的doGetBean已经是在单例方式下创建Bean对象的方法,一般来说do开头的方法都是实际干活的方法,像下图中的doGetBean doCreateBean 。

而initializeBean方法是在Bean 初始化和实例化之后,走传统意义上的Spring生命周期里面核心方法时所调用到的,这里不展开讲,就比如下列的applyBeanPostProcessorsBeforeInitialization方法,这个方法如果不太熟悉,那么postProcessBeforeInitialization这个方法你一定很熟悉,因为这个就是BeanPostProcessor bean的后置处理器的方法。至此 我们已经在方向上定位到了,setApplicationContext对于 自己创建的类的属性赋值,是在Bean的后置处理器上。

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    if(SpringUtil.applicationContext == null) {
        SpringUtil.applicationContext = applicationContext;
    }
}

会在initializeBean 在实例化和初始化之后调用, 在后置处理器的前置before方法中触发,会如下触发一系列的后置处理器的前置方法

for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
    BeanPostProcessor processor = (BeanPostProcessor)var4.next();
    current = processor.postProcessBeforeInitialization(result, beanName);
    if (current == null) {
        return result;
    }
}

我们知道 ,Bean的后置处理器有很多种,不同的类的实现,最终会被所有单例对象去调用到,下列是后置处理器的唯二的方法

  1. postProcessBeforeInitialization
  2. postProcessAfterInitialization

后置处理器 ApplicationContextAwareProcessor

实际作为后置处理器的类是:
ApplicationContextAwareProcessor

org/springframework/spring-context/5.2.2.RELEASE/spring-context-5.2.2.RELEASE.jar!/org/springframework/context/support/ApplicationContextAwareProcessor.class

@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (!(bean instanceof EnvironmentAware) && !(bean instanceof EmbeddedValueResolverAware) && !(bean instanceof ResourceLoaderAware) && !(bean instanceof ApplicationEventPublisherAware) && !(bean instanceof MessageSourceAware) && !(bean instanceof ApplicationContextAware)) {
        return bean;
    } else {
        AccessControlContext acc = null;
        if (System.getSecurityManager() != null) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged(() -> {
                this.invokeAwareInterfaces(bean);
                return null;
            }, acc);
        } else {
            this.invokeAwareInterfaces(bean);
        }

        return bean;
    }
}

可以看到,在后置处理器的前置postProcessBeforeInitialization里,对实例化和初始化完成的对象是有做到过滤的,满足条件才可以使用

bean instanceof ApplicationContextAware

大部分的bean是不会满足上述条件的,所以大部分只是走完判断,这个后置处理器的before方法就结束了。
只有满足代码中的条件 才能触发this.invokeAwareInterfaces(bean) 的核心方法

这里是实现了ApplicationContextAware if条件的最后一个条件,所以继续

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);
    }

}

这里是核心的调用方法 setApplicationContext,最终调用到了实际的我们的业务方法!

ApplicationContextAwareProcessor的创建

还有一小块疑问,那就是Bean的后置处理器是什么时候创建的呢?继续往下看


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());
    }

applicationContext是构造器注入的属性,最终我们自己实现类 的setApplicationContext的入参也是从后置处理器赋值的

那什么时候初始化的后置处理器?
在这里插入图片描述根据初始化的位置,我们知道,AbstractApplicationContext.refresh()是我们Spring启动的入口,在prepareBeanFactory的方法中,有下列的内容,会创建后置处理器并且添加到beanFactory中。

this.prepareBeanFactory(beanFactory);

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

这样我们也知道了ApplicationContextAwareProcessor的后置处理器是在这里创建的

注意: 并不是所有的后置处理器都是在这里创建,比如你自己创建的后置处理器,是在refresh方法中的这一步骤调用到的。

this.registerBeanPostProcessors(beanFactory);

好了,ApplicationContextAware底层原理详解这一篇我们就讲完了!

❤❤❤

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值