Spring5源码解析3-refresh方法初探
接上回分析完register(annotatedClasses);
后,现在来看一下refresh();
方法。
// new AnnotationConfigApplicationContext(AppConfig.class); 源码
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
//调用默认无参构造器,里面有一大堆初始化逻辑
this();
//把传入的Class进行注册,Class既可以有@Configuration注解,也可以没有@Configuration注解
//怎么注册? 委托给了 org.springframework.context.annotation.AnnotatedBeanDefinitionReader.register 方法进行注册
// 传入Class 生成 BeanDefinition , 然后通过 注册到 BeanDefinitionRegistry
register(annotatedClasses);
//刷新容器上下文
refresh();
}
refresh方法
点开refresh();
方法,里面调用了超级多的方法,我们一个个来看。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//准备上下文,设置其启动日期和活动标志,执行属性源的初始化
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//调用子类 refreshBeanFactory()方法
//获取 BeanFactory 实例 DefaultListableBeanFactory , DefaultListableBeanFactory 实现了 ConfigurableListableBeanFactory 接口
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//配置 beanFactory 上下文
//1.添加 ApplicationContextAwareProcessor 和 ApplicationListenerDetector
//2.忽略部分类型的自动装配
//3.注册特殊的依赖类型,并使用相应的autowired值
//4.注册默认的environment beans
//5.设置environment beans
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);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
prepareRefresh();
prepareRefresh();
做的事情比较简单:准备上下文,设置其启动日期和活动标志,执行属性源的初始化。
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
} else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment.
//这是一个空方法,AnnotationConfigApplicationContext 并没有 Override 改方法
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
//默认情况下,earlyApplicationListeners 为 null
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
} else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
obtainFreshBeanFactory();
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
refreshBeanFactory();
是一个抽象方法,它有两个具体是实现:
AnnotationConfigApplicationContext
继承 GenericApplicationContext
,所以很显然此处执行的应该是GenericApplicationContext
类中的方法。GenericApplicationContext
的refreshBeanFactory()
源码如下:
//GenericApplicationContext#refreshBeanFactory 源码
@Override
protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
this.beanFactory.setSerializationId(getId());
}
obtainFreshBeanFactory();
方法最后调用 getBeanFactory();
方法,并且返回ConfigurableListableBeanFactory
对象。
getBeanFactory();
,顾名思义就是获取BeanFactory
,Spring中使用的是 DefaultListableBeanFactory
,该类也同时实现了ConfigurableListableBeanFactory
接口。
prepareBeanFactory(beanFactory);
prepareBeanFactory(beanFactory);
源码比较简单:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
//增加 BeanPostProcessor 实例 ApplicationContextAwareProcessor
//ApplicationContextAwareProcessor 主要作用是对 Aware接口的支持,如果实现了相应的 Aware接口,则注入对应的资源
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//默认情况下,只忽略BeanFactoryAware接口,现在新增忽略如下类型的自动装配
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
//注册自动装配规则,如果发现依赖特殊类型,就使用该指定值注入
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
//注册默认的environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
// Environment
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
// System Properties
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
// System Environment
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
ApplicationContextAwareProcessor
prepareBeanFactory(beanFactory);
方法中往beanFactory
中添加了一个ApplicationContextAwareProcessor
对象:beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
。
ApplicationContextAwareProcessor
类实现了BeanPostProcessor
接口,其中主要是 Override 了postProcessBeforeInitialization
方法,其作用主要是用来对 Aware
系列接口的支持,发现Bean
实现了Aware
系列接口,就调用其相应的方法,具体为哪些Aware
接口,请查看源码:
//ApplicationContextAwareProcessor#postProcessBeforeInitialization 源码
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if (System.getSecurityManager() != null &&
(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
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 Aware) {
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);
}
}
}
程序运行到这里,再看看一下Spring容器中有哪些数据:
6个
BeanDefinition
对象3 个单例
Bean
2 个
BeanPostProcessor
postProcessBeanFactory(beanFactory);
这是一个留给子类去拓展的空方法,AnnotationConfigApplicationContext
类中的该方法没有做任何事情。
未完待续......
源码学习笔记:https://github.com/shenjianeng/spring-code-study
欢迎关注公众号:
Spring5源码解析3-refresh方法初探的更多相关文章
- Spring5源码解析-Spring框架中的单例和原型bean
Spring5源码解析-Spring框架中的单例和原型bean 最近一直有问我单例和原型bean的一些原理性问题,这里就开一篇来说说的 通过Spring中的依赖注入极大方便了我们的开发.在xml通过& ...
- Spring5源码解析-论Spring DispatcherServlet的生命周期
Spring Web框架架构的主要部分是DispatcherServlet.也就是本文中重点介绍的对象. 在本文的第一部分中,我们将看到基于Spring的DispatcherServlet的主要概念: ...
- Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean
Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean 七千字长文深刻解读,Spirng中是如何初始化单例bean的,和面试中最常问的Sprin ...
- 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例
前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...
- [Java多线程]-Thread和Runable源码解析之基本方法的运用实例
前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...
- Spring5源码解析_IOC之容器的基本实现
前言: 在分析源码之前,我们简单回顾一下SPring核心功能的简单使用: 容器的基本用法 Bean是Spring最核心的东西,Spring就像是一个大水桶,而Bean就是水桶中的水,水桶脱离了水就没有 ...
- 一文带你解读Spring5源码解析 IOC之开启Bean的加载,以及FactoryBean和BeanFactory的区别。
前言 通过往期的文章我们已经了解了Spring对XML配置文件的解析,将分析的信息组装成BeanDefinition,并将其保存到相应的BeanDefinitionRegistry中,至此Spring ...
- Spring5源码解析2-register方法注册配置类
接上回已经讲完了this()方法,现在来看register(annotatedClasses);方法. // new AnnotationConfigApplicationContext(AppCon ...
- Spring5源码解析4-refresh方法之invokeBeanFactoryPostProcessors
invokeBeanFactoryPostProcessors(beanFactory);方法源码如下: protected void invokeBeanFactoryPostProcessors( ...
随机推荐
- 最短路算法 Dijkstra 入门
dijkstra算法 是一种单源点最短路算法求出一个点到其他所有点的最短路. 给你这样的一个图,需要求出1号点到其他点的最短距离是多少. 首先我们开一个数组 d[N],d[x] 代表着从起点出发到x点 ...
- Python远程连接MySQL数据库
使用Python连接数据库首先需要安装Python的数据库驱动. 我的本地只装了Python,并没有装MySQL,当我使用命令: sudo pip install mysql-python 安装驱动( ...
- 【4】Logistic回归
前言 logistic回归的主要思想:根据现有数据对分类边界建立回归公式,以此进行分类 所谓logistic,无非就是True or False两种判断,表明了这其实是一个二分类问题 我们又知道回归就 ...
- 【Nginx】基于Consul+Upsync+Nginx实现动态负载均衡
一.Http动态负载均衡 什么是动态负载均衡 动态负载均衡实现方案 常用服务器注册与发现框架 二.Consul快速入门 Consul环境搭建 三.nginx-upsync-module nginx-u ...
- ajax交互案例
数据交互是前端很重要的一部分,静态页是基础,而交互才是网页的精髓.交互又分为人机交互和前后端数据交互,现阶段的互联网下,大部分的网站都要进行前后端数据交互,如何交互呢?交互的流程大概就是前端发送数据给 ...
- Java并发笔记——单例与双重检测
单例模式可以使得一个类只有一个对象实例,能够减少频繁创建对象的时间和空间开销.单线程模式下一个典型的单例模式代码如下: ① class Singleton{ private static Single ...
- Java连载31-递归方法练习、面向对象
一.实现阶乘(一种用递归,一种普通方法) public static void main(String[] args) { System.out.println(factorial(5)); Syst ...
- Unity3D_08_XML文件创建,读取,修改,添加
今天在工作之余学习了一下关于Unity中关于XML的部分. 在这里要注意添加两个命名空间,如下: 一.xml的解析 首先新建一个xml,可以命名为item.xml,拖进assets里面,内容如下: & ...
- Hbase 统计表行数的3种方式总结
有些时候需要我们去统计某一个Hbase表的行数,由于hbase本身不支持SQL语言,只能通过其他方式实现.可以通过一下几种方式实现hbase表的行数统计工作: 1.count命令 最直接的方式是在hb ...
- 基于Arduino和Blynk平台的远程控制智能小车
/------转载请附上本文链接 https://i.cnblogs.com/EditArticles.aspx?opt=1 -------啦啦啦我是快乐的分割线- ------------/ 小车图 ...