springboot源码解析-管中窥豹系列之aware(六)
2021-02-09 04:08
1256 查看
一、前言
- 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; @Component public 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);
publi 15a8 c 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<>(); @Override public 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什么时候执行的呢?
-
这个比较麻烦,我们后面单开一节再详细的去看。
欢迎关注微信公众号:丰极,更多技术学习分享。
相关文章推荐
- springboot源码解析-管中窥豹系列
- springboot源码解析-管中窥豹系列之BeanDefinition(八)
- springboot源码解析-管中窥豹系列之web服务器(七)
- Spring Boot系列(三):Spring Boot整合Mybatis源码解析
- Spring Boot系列(四):Spring Boot源码解析
- 深入Spring源码系列--Spring/Springboot 注解失效原因解析
- 【源码解读系列五】深入剖析Springboot启动原理的底层源码
- Spring Boot系列实战文章合集(附源码)
- SpringBoot源码解析:tomcat启动分析
- (六)SpringBoot源码解析----springboot 与 tomcat
- SpringBoot2.x系列教程(二十九)freemarker自动配置源码解析
- spring boot 源码解析5-SpringApplication#run第5步
- springboot之启动原理解析及源码阅读
- Springboot系列:Springboot与Thymeleaf模板引擎整合基础教程(附源码)
- Springboot系列:Springboot与Thymeleaf模板引擎整合基础教程(附源码)
- Springboot系列:Springboot与Thymeleaf模板引擎整合基础教程(附源码)
- Spring Boot 源码解析,一步步分析启动原理
- SpringBoot系列教程web篇之Post请求参数解析姿势汇总
- SpringBoot 源码解析 (三)----- Spring Boot 精髓:启动时初始化数据
- Spring系列(五):Spring AOP源码解析