Spring创建Bean的过程
# 环境搭建
# refresh() 说明
Spring IoC 容器对 Bean 定义资源的载入是从 refresh()
函数开始的,refresh()
是一个模板方法,refresh()
方法的作用是在创建 IoC 容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在 refresh()
之后使用的是新建立起来的 IoC 容器。
refresh()
是 AbstractApplicationContext 内的模板方法,可以被子类重写。
refresh()
包含 12 关键方法:
prepareRefresh()
obtainFreshBeanFactory()
prepareBeanFactory()
postProcessBeanFactory()
invokeBeanFactoryPostProcessors()
registerBeanPostProcessors()
initMessageSource()
initApplicationEventMulticaster()
onRefresh()
registerListeners()
finishBeanFactoryInitialization(beanFactory)
finishRefresh()
启动 Spring 容器经常采用两种方案:
- AnnotationConfigApplicationContext 直接读取配置类加载 Bean
- ClasspathXmlApplicationContext 通过配置文件加载 Bean
# AnnotationConfigApplicationContext
如果通过配置类启动容器,可以使用 AnnotationConfigApplicationContext 进行创建。
没有重写 refresh()
内的12个方法。
# ClassPathXmlApplicationContext
如果通过注解文件启动容器,可以使用 ClassPathXmlApplicationContext 进行创建。
# refresh() 核心方法
# 1. prepareRefresh()
为 applicationContext 容器做准备,设置其启动日期和活动标志,以及执行任何属性源的初始化。
# 2. obtainFreshBeanFactory()
该方法主要是获取到应用上下文维护的 beanFactory,默认是 DefaultListableBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
2
3
4
# refreshBeanFactory()
调用 GenericApplicationContext 的 refreshBeanFactory()
方法。其首先应用 CAS 思想设置刷新标志,然后为 beanFactory 设置序列化ID,默认是application。
@Override
protected final void refreshBeanFactory() throws IllegalStateException {
// 通过CAS设置当前为正在refresh
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
// 设置序列化ID
this.beanFactory.setSerializationId(getId());
}
2
3
4
5
6
7
8
9
10
11
当前对象 this 指的是 AnnotationConfigServletWebServerApplicationContext,而 refreshBeanFactory 调用是其祖父类 GenericApplicationContext 。
# getId()
AbstractApplicationContext 的 getId()
方法。
private String id = ObjectUtils.identityToString(this);
public String getId() {
return this.id;
}
2
3
4
5
返回结为:org.springframework.context.annotation.AnnotationConfigApplicationContext@2dda6444
,就是 Main 函数中创建的 Spring 容器。
# setSerializationId()
public void setSerializationId(@Nullable String serializationId) {
if (serializationId != null) { // 成立
// serializableFactories 是类变量
// 将<序列化ID,容器>放到map中,可以根据ID找到容器
serializableFactories.put(serializationId, new WeakReference<>(this));
}
else if (this.serializationId != null) {
serializableFactories.remove(this.serializationId);
}
this.serializationId = serializationId;
}
2
3
4
5
6
7
8
9
10
11
# getBeanFactory()
调用 GenericApplicationContext 的 getBeanFactory()
方法,返回当前 beanFactory 对象,默认是 DefaultListableBeanFactory 类型。
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
2
3
4
# 3. prepareBeanFactory()
该方法主要是对 beanFactory 做了一些基础设置的配置,比如 BeanClassLoader、BeanExpressionResolver、ApplicationContextAwareProcessor、ApplicationListenerDetector 监听器检测器以及默认的环境信息 bean。并设置了哪些不需要自动注入以及哪些已经解析过可以直接使用。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置类加载器,默认是RestartClassLoader
beanFactory.setBeanClassLoader(getClassLoader());
// 设置表达式解析器,比如SPEL语法就是该解析器内维护的SpelExpressionParser进行处理的
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 注册一个属性编辑器注册器,用于将字符串值转换为特定类型的对象的组件
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 为beanFactory配置一些回调,这些在bean实例化过程中会被触发
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 告诉BeanFactory在进行依赖注入时忽略指定的接口,在进行依赖注入时,BeanFactory将不会自动注入实现了这些接口的bean
// 我们可以通过其他方式手动处理这些依赖关系,例如通过自定义的注入逻辑或者使用特定的注解。
// 当我们希望在某些接口上使用特定的注解来进行依赖注入时,可以将这些接口添加到ignoreDependencyInterface列表中,以避免自动注入的冲突。
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注册可解析的依赖项,当遇到这个特定的依赖项时,不需要进行自动解析,而是使用我们提供的值或对象
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 添加ApplicationListenerDetector后置处理器
// 可以在Bean的初始化过程中检测并处理实现了ApplicationListener接口的Bean,将其注册为应用程序上下文的事件监听器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 如果不包含,则注册
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 注册三个环境相关的Bean对象
// 环境对象
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
// 系统属性Map:java.runtime.version、user.name等等
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
// 系统环境Map:比如当前PATH、USER、HOME等等
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
// 注册完成后,singletonObjects单例池中多了三个Bean对象
}
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