版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
前言:一直想详细了解下Spring容器初始化和bean创建过程,今天抽空通过翻阅各种资料,对Spring容器初始化和bean的创建有了大概了解。
Spring容器初始化过程(注解)
以AnnotationConfigApplicationContext为例:
查看继承图:
从AnnotationConfigApplicationContext源码分析
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(UserConfig.class);
AnnotationConfigApplicationContex主要代码
public AnnotationConfigApplicationContext(Class... annotatedClasses) {
this();
//2.注册bean配置类
this.register(annotatedClasses);
//3.刷新上下文
this.refresh();
}
1.this() 初始化bean读取器和扫描器
public AnnotationConfigApplicationContext() {
//在IOC容器中初始化一个 注解bean读取器AnnotatedBeanDefinitionReader
this.reader = new AnnotatedBeanDefinitionReader(this);
//在IOC容器中初始化一个 按类路径扫描注解bean的 扫描器
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
2. register(annotatedClasses)
注册bean配置类, AnnotationConfigApplicationContext容器通过AnnotatedBeanDefinitionReader的registerBean方法实现注解bean的读取,具体源码如下:AnnotationConfigApplicationContext.java中register方法
public void registerBean(Class<?> annotatedClass) {
doRegisterBean(annotatedClass, null, null, null);
}
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//将Bean配置类信息转成容器中AnnotatedGenericBeanDefinition数据结构, AnnotatedGenericBeanDefinition继承
//自BeanDefinition作用是定义一个bean的数据结构,下面的getMetadata可以获取到该bean上的注解信息
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
//@Conditional装配条件判断是否需要跳过注册
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(instanceSupplier);
//解析bean作用域(单例或者原型),如果有@Scope注解,则解析@Scope,没有则默认为singleton
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
//作用域写回BeanDefinition数据结构, abd中缺损的情况下为空,将默认值singleton重新赋值到abd
abd.setScope(scopeMetadata.getScopeName());
//生成bean配置类beanName
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//通用注解解析到abd结构中,主要是处理Lazy, primary DependsOn, Role ,Description这五个注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
//如果配置@Primary注解,则设置当前Bean为自动装配autowire时首选bean
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
//设置当前bean为延迟加载
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
//其他注解,则添加到abd结构中
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
//根据beanName和bean定义信息封装一个BeanDefinitionHolder,其实就是一个 beanname和BeanDefinition的映射
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
//创建代理对象 借助AnnotationConfigUtils工具类解析通用注解
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// new ConcurrentHashMap<String, BeanDefinition>(256);用于保存注bean定义信息(beanname 和 beandefine映射)注册到IOC容器中
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
目的:完成bean配置类本身的解析和注册。将其以键值对的形式保存到IOC容器中。
3 refresh()刷新上下文
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1.刷新前的预处理
prepareRefresh();
// 2.获取刷新后的内部Bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//3.BeanFactory的预准备工作
prepareBeanFactory(beanFactory);
try {
// BeanFactory准备工作完成后,可以做一些后置处理工作
//4.空方法,用于在容器的子类中扩展
postProcessBeanFactory(beanFactory);
// 5. 执行BeanFactoryPostProcessor的方法,BeanFactory的后置处理器
//在BeanFactory标准初始化之后执行的
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册BeanPostProcessor(Bean的后置处理器),用于拦截bean创建过程
registerBeanPostProcessors(beanFactory);
// 7. 初始化MessageSource组件(做国际化功能;消息绑定,消息解析).
initMessageSource();
// 8. 初始化事件派发器
initApplicationEventMulticaster();
//9.可以用于子类实现在容器刷新时自定义逻辑初始化
onRefresh();
// 10. 注册时间监听器,将ApplicationListener注册到容器中来
registerListeners();
// 11. 初始化所有剩下的单实例bean,单例bean在初始化容器时创建,懒加载在调用的时候创建
finishBeanFactoryInitialization(beanFactory);
//12. 完成BeanFactory的初始化创建工作,IOC容器就创建完成
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();
}
}
}
refresh刷新上下文字方法1到12,bean的创建过程在第11个方法。具体bean的创建方法我们可以参考这篇文章Spring|容器初始化流程及源码分析