文章目录

  • Spring容器初始化过程(注解)
    • 1.this() 初始化bean读取器和扫描器
    • 2. register(annotatedClasses)
    • 3 refresh()刷新上下文

前言:一直想详细了解下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读取器AnnotatedBeanDefinitionReaderthis.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,没有则默认为singletonScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);//作用域写回BeanDefinition数据结构, abd中缺损的情况下为空,将默认值singleton重新赋值到abdabd.setScope(scopeMetadata.getScopeName());//生成bean配置类beanNameString 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时首选beanif (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|容器初始化流程及源码分析

Spring容器初始化和bean创建过程相关推荐

  1. Spring 源码解析 - Bean创建过程 以及 解决循环依赖

    一.Spring Bean创建过程以及循环依赖 上篇文章对 Spring Bean资源的加载注册过程进行了源码梳理和解析,我们可以得到结论,资源文件中的 bean 定义信息,被组装成了 BeanDef ...

  2. Spring容器中的Bean是否会被GC呢?

    Spring容器中的Bean是否会被GC呢?最近好几次被校招实习生问及,对于初学者来说,这应该是一个有意思的问题,鉴于此,笔者顺便写个这个文档. 1.Spring容器中Bean的作用域 当通过Spri ...

  3. spring容器里存取bean

    spring容器里存取bean spring容器存取bean的过程是什么? Map中是怎么存放值的? 首先 , 先把各个对象码出来,把过程搭建好 1 . 建配置类 , 为这个类配置了一个包扫描 , 代 ...

  4. Spring的初始化和对象创建流程

    Spring容器的初始化和对象创建流程(代码方面): 如图: 1.Spring容器初始化流程: 文字说明: 在ClassPathXmlApplicationContext的构造函数中: super(p ...

  5. Spring容器启动流程+Bean的生命周期【附源码】

    如果对SpringIoc与Aop的源码感兴趣,可以访问参考:https://javadoop.com/,十分详细. 文章目录 Spring容器的启动全流程 Spring容器关闭流程 Bean 的生命周 ...

  6. 【SpringBoot】在普通类中获取spring容器中的bean

    这段时间公司搞封闭开发,做一个联通总部的客服系统项目,是基于springboot的.在开发工程中遇到一个页面datagrid数据排序的功能,因为有多个表的数据都要用到排序功能,于是我就写了一个排序功能 ...

  7. 当Spring 容器初始化完成后执行某个方法

    当Spring 容器初始化完成后执行某个方法 实现ApplicationListener 使用注解:`@PostConstruct` 实现ApplicationListener 在做web项目开发中, ...

  8. Spring注解驱动开发第11讲——面试官让我说说:如何使用FactoryBean向Spring容器中注册bean?

    写在前面 经过前面的学习,我们知道可以通过多种方式向Spring容器中注册bean.可以使用@Configuration注解结合@Bean注解向Spring容器中注册bean:可以按照条件向Sprin ...

  9. Spring容器初始化完成后执行业务逻辑的三种方式

    一  业务背景 监听应用容器启动完毕并扫描容器类特定的Dubbo服务,并把相关元数据注册到网关. 二 思路 1  在容器启动构造元数据上报到网关,影响应用启动性能: 2  监听容器启动完毕后构造元数据 ...

最新文章

  1. Java 接口和继承
  2. 【网络协议】专题总结以及网络协议高频面试题汇总(8篇)
  3. Win11关机后自动开机怎么办 Win11关机后自动开机的解决方法
  4. 简直要逆天!超炫的 HTML5 粒子效果进度条
  5. 20200329:K 个一组翻转链表(leetcode25)
  6. 【FFmpeg小点记】AV_DISPOSITION_ATTACHED_PIC
  7. 免费获得卡巴斯基key的方法
  8. pngquanttinypng 使用教程
  9. 图像相似度对比分析软件,简单图像相似度对比图
  10. donet 微服务开发 学习-AOP框架基础
  11. 有长度,有角度,有点积,有人性
  12. 测试报告包含哪些内容?(超详细,带图)
  13. mp3转wav,详细方法介绍
  14. 修改oracle用户密码永不过期的方法
  15. 【github】上有意思的深度学习项目——照片漫画风
  16. 4133:垃圾炸弹 百练noi Java枚举
  17. java基础,进阶(二)
  18. TCP状态转换图文解说
  19. Facebook pop
  20. Holm–Bonferroni method

热门文章

  1. excelvba怎么设置不打开文件自动保存_自从有了这个工具,我的Office操作已经快到慢不下来了!(升级篇)...
  2. 嵌入式笔录(2)-电阻串联与并联
  3. vb.net2019-读取定宽文本文件-比如日志
  4. 【深度学习】在PyTorch中使用 LSTM 进行新冠病例预测
  5. 【学术相关】魔术乘法:张成奇教授40年磨一剑!
  6. 30万奖金等你拿,“信也科技杯”第五届数据解决方案应用大赛火热报名中!...
  7. Github标星8.3k+,Tensorflow 2.0的代码实现及教学材料(“龙书”)公布下载了!
  8. [PLM专题] 十分钟了解文本分类通用训练技巧
  9. 超级菜鸟如何入门数据分析?
  10. 25篇最新CV领域综述性论文速递!涵盖15个方向:目标检测/图像处理/姿态估计/医学影像/人脸识别等方向