一、前言

  • Springboot源码解析是一件大工程,逐行逐句的去钻研代码,会很干燥,也不容易坚持下去。
  • 咱们不谋求大而全,而是试着每次去钻研一个小知识点,最终聚沙成塔,这就是咱们的springboot源码管中窥豹系列。

二、ApplicationContextAware

  • 假如咱们想应用某个bean, 如果是在@Component类上面,间接用@Autowired援用就行了
  • 假如咱们想在某个静态方法外面用,就不能用下面的办法了
  • 你可能想用new Bean()的形式,new一个,然而这个bean外面的@Autowired援用用不了
  • 如果有一个动态的全局ApplicationContext就好了,用spring的能力获取bean: ApplicationContext.getBean(clazz)
  • ApplicationContextAware就是这个用途
public interface ApplicationContextAware extends Aware {    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;}public interface Aware {}

咱们写一个实现类:

import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;@Componentpublic class SpringContextUtil implements ApplicationContextAware {    private static ApplicationContext applicationContext;    @Override    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {        SpringContextUtil.applicationContext = applicationContext;    }    private static ApplicationContext getApplicationContext() {        return applicationContext;    }    public static <T> T getBean(Class<T> clazz){        return getApplicationContext().getBean(clazz);    }}
  • 通过setApplicationContext,把applicationContext赋值到本地动态变量
  • 通过ApplicationContext的getBean就能够在静态方法中应用任何bean的能力了

三、源码剖析

咱们进入SpringApplication的run办法:

public ConfigurableApplicationContext run(String... args) {    ...    try {                ...        refreshContext(context);                ...    }    catch (Throwable ex) {              ...    }    ...    return context;}

咱们进入refreshContext(context)外部:

public void refresh() throws BeansException, IllegalStateException {    synchronized (this.startupShutdownMonitor) {        // Prepare this context for refreshing.        prepareRefresh();        // Tell the subclass to refresh the internal bean factory.        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();        // Prepare the bean factory for use in this context.        prepareBeanFactory(beanFactory);        try {            // Allows post-processing of the bean factory in context subclasses.            postProcessBeanFactory(beanFactory);            // Invoke factory processors registered as beans in the context.            invokeBeanFactoryPostProcessors(beanFactory);            // Register bean processors that intercept bean creation.            registerBeanPostProcessors(beanFactory);            // Initialize message source for this context.            initMessageSource();            // Initialize event multicaster for this context.            initApplicationEventMulticaster();            // Initialize other special beans in specific context subclasses.            onRefresh();            // Check for listener beans and register them.            registerListeners();            // Instantiate all remaining (non-lazy-init) singletons.            finishBeanFactoryInitialization(beanFactory);            // Last step: publish corresponding event.            finishRefresh();        }        catch (BeansException ex) {            if (logger.isWarnEnabled()) {                logger.warn("Exception encountered during context initialization - " +                        "cancelling refresh attempt: " + ex);            }            destroyBeans();            cancelRefresh(ex);            throw ex;        }        finally {            resetCommonCaches();        }    }}

这个refresh是spring的外围办法,当前会屡次用到,内容太多,咱们这次只关注一个办法:

  • prepareBeanFactory(beanFactory);
public void refresh() throws BeansException, IllegalStateException {    synchronized (this.startupShutdownMonitor) {        ...        // Prepare the bean factory for use in this context.        prepareBeanFactory(beanFactory);        ...    }}

咱们先看prepareBeanFactory(beanFactory):

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {    ...    // Configure the bean factory with context callbacks.    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));    ...    }

咱们看一下这个addBeanPostProcessor办法

private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();@Overridepublic void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {    Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");    // Remove from old position, if any    this.beanPostProcessors.remove(beanPostProcessor);    // Track whether it is instantiation/destruction aware    if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {        this.hasInstantiationAwareBeanPostProcessors = true;    }    if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {        this.hasDestructionAwareBeanPostProcessors = true;    }    // Add to end of list    this.beanPostProcessors.add(beanPostProcessor);}
  • 先remove,再add
  • beanPostProcessors是一个线程平安的list: CopyOnWriteArrayList
  • 咱们往下看看new ApplicationContextAwareProcessor(this),留神:this是ApplicationContext
class ApplicationContextAwareProcessor implements BeanPostProcessor {    private final ConfigurableApplicationContext applicationContext;    private final StringValueResolver embeddedValueResolver;    /**     * Create a new ApplicationContextAwareProcessor for the given context.     */    public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {        this.applicationContext = applicationContext;        this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());    }    @Override    @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;        }        AccessControlContext acc = null;        if (System.getSecurityManager() != null) {            acc = this.applicationContext.getBeanFactory().getAccessControlContext();        }        if (acc != null) {            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {                invokeAwareInterfaces(bean);                return null;            }, acc);        }        else {            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);        }    }}
  • 构造方法,把applicationContext设到本地变量上
  • 实现接口的办法:postProcessBeforeInitialization,回调的时候会用,次要是校验权限
  • 最上面的invokeAwareInterfaces是个公有的外围回调办法,依据不同类型,有不同回调

咱们看到除了ApplicationContextAware,还有其它的aware, 总共6个

  • EnvironmentAware:环境变量
  • EmbeddedValueResolverAware:值解析器
  • ResourceLoaderAware:资源加载器
  • ApplicationEventPublisherAware:事件公布器
  • MessageSourceAware:信息处理器
  • ApplicationContextAware:spring容器

比方咱们想用全局的环境变量,就有EnvironmentAware,想用spring的事件就用ApplicationEventPublisherAware,等等

  • 起源找到了,ApplicationContextAwareProcessor什么时候执行的呢?
  • 这个比拟麻烦,咱们前面单开一节再具体的去看。

欢送关注微信公众号:丰极,更多技术学习分享。