AI智能
改变未来

springboot源码解析-管中窥豹系列之aware(六)


一、前言

  • 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;@Overridepublic 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);
publi15a8c 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 anythis.beanPostProcessors.remove(beanPostProcessor);// Track whether it is instantiation/destruction awareif (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {this.hasInstantiationAwareBeanPostProcessors = true;}if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {this.hasDestructionAwareBeanPostProcessors = true;}// Add to end of listthis.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@Nullablepublic 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什么时候执行的呢?

  • 这个比较麻烦,我们后面单开一节再详细的去看。

  • 目录:
    springboot源码解析-管中窥豹系列

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

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » springboot源码解析-管中窥豹系列之aware(六)