refreshContext

refreshContext

  • 这是容器的初始化的地方,通过调用 refresh() 来实现,定义在 AbstractApplicationContext 接口里。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.准备刷新
//容器预先准备
prepareRefresh();

// Tell the subclass to refresh the internal bean factory.刷新bean factory
//创建bean工厂,如果有则销毁
//里面实现对beanDefinition的装载
// 告知子类要初始化BeanFactory,BeanDefinition信息的读取是在子类的
// refreshBeanFactory()方法里完成的
//beanDefinition信息是通过ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()里的refreshBeanFactory()来完成的
//而这个方法则是在AbstractRefreshableApplicationContext实现的。
//创建bean工厂,如果有则销毁这个操作就是在refreshBeanFactory()
//refreshBeanFactory()中是通过loadBeanDefinitions()来完成BeanDefinition的定位,而loadBeanDefinitions()是一个抽象的方法,具体由AbstractBeanDefinitionReader里的loadBeanDefinitions()来实现。
//在loadBeanDefinitions()通过DefaultResourceLoader的getResource方法里返回resource对象
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// Prepare the bean factory for use in this context.为这个context准备bean factory
//配置bean工厂的标准上下文特性,如类装载器、PostProcesser等
prepareBeanFactory(beanFactory);

try {
// Allows post-processing of the bean factory in context subclasses.
//beanFactory的后置处理器
//模板方法,在bean定义被装载后,提供一个修改容器beanFactory的入口
postProcessBeanFactory(beanFactory);

// Invoke factory processors registered as beans in the context.
//实现beanFactory的后置处理器
//在Bean未开始实例化时,对Definition定义的修改的入口
//常见的PropertyPlaceholderConfigurer在这里被调用
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
//注册后置处理器
//注册用于拦截bean创建过程的BeanPostProdessors
registerBeanPostProcessors(beanFactory);

// Initialize message source for this context.
//初始化messageSource,国际化
initMessageSource();

// Initialize event multicaster for this context.
//注册事件发布器
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
//初始化其他特殊的bean
onRefresh();

// Check for listener beans and register them.
//注册监听器
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
//完成beanFactory初始化
//里面的preInstantiateSingletons会完成单例对象的创建
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.
//销毁已注册的bean
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();
}
}
}
  • beanDefinition信息是通过ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()里的refreshBeanFactory()来完成的,而这个方法则是在AbstractRefreshableApplicationContext实现的。
    • 如果容器已经存在,那么销毁并且关闭该容器,保证每次产生的都是新的容器
      1.png
  • DefaultListableBeanFactory其实是一个最基础的容器,很多容器都是基于这个容器来作扩展,那么这个容器里自然也包含了很多基础重要的功能,那么通过loadBeanDefinitions()来完成BeanDefinition信息的载入的,这里是委托子类来完成这个工作的。
1
2
3
4
5
6
7
8
9
10
11
//抽象类,具体的resource定位跟BeanDefinition的载入是委托子类来完成的
/**
* Load bean definitions into the given bean factory, typically through
* delegating to one or more bean definition readers.
* @param beanFactory the bean factory to load bean definitions into
* @throws BeansException if parsing of the bean definitions failed
* @throws IOException if loading of bean definition files failed
* @see org.springframework.beans.factory.support.PropertiesBeanDefinitionReader
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
*/
protected abstract void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException;

具体实现看源码

  • 总结下Resource定位BeanDefinition的流程
    1.FileSystemXmlApplicationContext里调用refresh()方法初始化IoC容器。
    2.在refresh()方法里调用obtainFreshBeanFactory()里面的refreshBeanFactory()来完成BeanDefinition的定位,而refreshBeanFactory()是由子类AbstractRefreshableApplicationContext来实现的。
    3.refreshBeanFactory()中是通过loadBeanDefinitions()来完成BeanDefinition的定位,而loadBeanDefinitions()是一个抽象的方法,具体由AbstractBeanDefinitionReader里的loadBeanDefinitions()来实现。
    4.在loadBeanDefinitions()通过DefaultResourceLoader的getResource方法里返回resource对象。
  • BeanDefinition的信息已经定位到了,第二步就是把定义的BeanDefinition在Ioc容器中转化成一个Spring内部标示的数据结构的过程。
    • 首先通过调用XML的解析器得到Document对象,此时这些Document对象并没有按照Spring的Bean规则进行解析,在完成通用的XML解析以后,才是按照Spring Bean规则进行解析的地方,这个过程在documentReader中实现,使用的documentReader是默认设置好的DefaultBeanDefinitionDocumentReader。
  • 将抽象好的BeanDefinition统一注册到IoC容器中,IoC容器是通过hashMap来维护BeanDefinition信息的,key为beanName,value为BeanDefinition。
  • BeanDefinition的注册是发生在BeanDefinition信息载入之后的, 通过registerBeanDefinition实现
  • 总的来说
    • spring ioc初始化流程就是resource定位 即寻找用户定义的bean资源,由ResourceLoader通过统一的接口Resource接口来完成 beanDefinition载入BeanDefinitionReader读取、解析Resource定位的资源成BeanDefinition载入到ioc中(通过HashMap进行维护BeanDefinition) BeanDefinition注册 即向IOC容器注册这些BeanDefinition, 通过registerBeanDefinition实现
    • BeanDefinition加载流程:定义BeanDefinitionReader解析xml的document BeanDefinitionDocumentReader解析document成beanDefinition
  • SpringBoot 对@SpringBootApplication注解的类的注入
    • 在prepareContext进行bean的加载
      2.png
    • load
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
//这个BeanDefinationLoader的实现类为org.springframework.boot.BeanDefinitionLoader,为springboot自定义的一个beanDefination的加载器,专门用来加载配置声明的类的
BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
//org.springframework.boot.BeanDefinitionLoader把beanDefination加载进spring的BeanDefinationRegistry中的方法
loader.load();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
private int load(Class<?> source) {
if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
// Any GroovyLoaders added in beans{} DSL can contribute beans here
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
load(loader);
}
if (isComponent(source)) {
//通过org.springframework.context.annotation.AnnotatedBeanDefinitionReader.AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry)来注册注解扫描的类定义
this.annotatedReader.register(source);
return 1;
}
return 0;
}
  • 在refreshContext进行bean的实例化(DI依赖注入)
    生成bean过程运用装饰器模式产生的bean都是beanWrapper(bean的增强)
    先自定义一个class
1
2
3
4
5
6
@Component
public class MyClass {
public MyClass() {
System.out.println("我创建了");
}
}

调试发现refresh方法里面的finishBeanFactoryInitialization(beanFactory)方法对MyClass实例化
4.png

  • 依赖注入怎么处理bean之间的依赖关系?
    其实就是通过在beanDefinition载入时,如果bean有依赖关系,通过占位符来代替,在调用getbean时候,如果遇到占位符,从ioc里获取bean注入到本实例来
    参考1
    参考2
    参考3
    参考4