首页 > 编程语言 >Spring源码分析-BeanDefination加载

Spring源码分析-BeanDefination加载

时间:2023-05-27 14:23:03浏览次数:38  
标签:bd configClass BeanDefination 处理 Spring 配置 源码 注解 解析

ConfigurationClassPostProcessor

img

解析配置类中有两类集合,一类是配置类、另一类是所有已解析的bd

  1. 从已有bd中过滤配置类

candidateNames:保存已被解析出来的所有待解析的bd名

​ configCandidates:candidateNames经过过滤的所有待解析的配置类bd

​ 过滤条件:

​ 检查BeanDefinition并设置 CONFIGURATION_CLASS_ATTRIBUTEfull 或者 lite

Full : 即类被 @Configuration 注解修饰 && proxyBeanMethods属性为true (默认为 true)

Lite : 被 @Component、@ComponentScan、@Import、@ImportResource 修饰的类 或者 类中有被 @Bean修饰的方法

  1. configCandidates.sort()

  2. 解析配置类

​ candidates:configCandidates,待解析配置类

​ alreadyParsed:

​ do:
parse():解析,生成bd元数据(configClasses)

processConfigurationClass

​ 1.@Conditional条件过滤(PARSE_CONFIGURATION阶段)-> shouldSkip

​ 2.递归解析配置类

​ SourceClass sourceClass = asSourceClass(configClass, filter);
​ do:
​ sourceClass = doProcessConfigurationClass()
​ while (sourceClass != null);

​ 3.configurationClasses.put(configClasse)

this.deferredImportSelectorHandler.process()

​ DeferredImportSelectorGroupingHandler#register(DeferredImportSelectorHolder)

​ DeferredImportSelectorGroupingHandler#rprocessGroupImports

​ validate():校验配置类的访问权限...

​ configClasses:本次循环解析出来的配置类(其中可能包含已经被解析过的)

​ configClasses.removeAll(alreadyParsed)

loadBeanDefinitions():加载元数据为bd(configClasses)

​ alreadyParsed.addAll(configClasses)

​ candidates.clear()

​ newCandidateNames:所有已解析的bd名

​ oldCandidateNames:candidateNames

​ 遍历newCandidateNames:

​ 过滤掉oldCandidateNames(剩下本次解析出来bd)

​ 如果是配置类且没有被解析过,则加入candidates中

​ candidateNames = newCandidateNames

​ while (!candidates.isEmpty())

doProcessConfigurationClass

  1. 处理 @Component 注解

    如果类被 @Component 修饰,则处理内部类:

    processMemberClasses:寻找并遍历内部类中的配置类,递归解析

  2. 处理 @PropertySource 注解

    解析注解属性,根据注解属性中的locations,加载配置并添加到environment中

  3. 处理 @ComponentScan注解

    根据注解属性扫描指定的包,便遍历bd中的配置类,递归解析

  4. 处理 @Import 注解

    processImports(); 该方法处理的包括 @Import、ImportSelector、 ImportBeanDefinitionRegistrar。这三个注解或接口都可以完成Bean的引入功能。

    • ImportSelector:分为延迟加载(DeferredImportSelector)和非延迟加载

      • 非延迟加载会通过selectImports()方法,获取导入的类,并遍历导入的类递归的processImports进行解析

      • 延迟加载会调用 DeferredImportSelectorHandler.handle()

        deferredImportSelectors.add(new DeferredImportSelectorHolder(configClass, importSelector))
        
    • ImportBeanDefinitionRegistrar:并不立即进行解析,而是保存到 configClass 相应的属性中

    • @Import:可以通过 @Import(XXX.class) 的方式,将XXX作为configClass进行递归的解析

  5. 处理 @ImportResource 注解

    解析注解属性,保存到 configClass 相应的属性中

  6. 处理 @Bean修饰的方法

    解析注解属性,保存到 configClass 相应的属性中

  7. 处理其他默认接口方法

    检测 配置类实现的接口中的默认方法是否被@Bean修饰,如果被修饰则也需要保存到 configClass 中

  8. 处理父类,如果存在,递归解析

loadBeanDefinitions

  1. shouldSkip?
  2. 处理被引入的(被 @Import 或者其他配置类内部引入)的情况
  3. 处理BeanMethod
  4. 处理ImportResource
  5. 处理ImportBeanDefinitionRegistrar:执行loadBeanDefinitionsFromRegistrars()方法进行导入

shouldSkip(metadata, phase)

如果phase为null,则先判断是不是配置类,如果是则走PARSE_CONFIGURATION逻辑,否则走REGISTER_BEAN逻辑

  1. 获取@Conditional上所有Condition

  2. Condition集合排序

  3. 如果ConditionConfigurationCondition,需要condition.getConfigurationPhase()来获取该Condition生效的阶段

  4. 如果生效阶段为null或生效阶段与phase匹配,则返回!condition.matches:即条件不匹配的话,应该跳过

    matches(context, metadata)中,context包含BeanDefinitionRegistry,metadata为引入条件注解的注解元信息

deferredImportSelectorHandler.process()

DeferredImportSelector类结构图

image-20230505205015350

image-20230505210427825

  1. DeferredImportSelectorGroupingHandler#register(DeferredImportSelectorHolder)

    1. group = getImportGroup:获取DeferredImportSelector的Group,AutoConfigurationImportSelector对应的Group是AutoConfigurationGroup
    2. group -> new DeferredImportSelectorGrouping(createGroup(group)) 放入 groupings
    3. 将DeferredImportSelectorHolder填充到上边new的对象里
    4. configurationClasses.put
  2. DeferredImportSelectorGroupingHandler#rprocessGroupImports

    遍历groupings(DeferredImportSelectorGrouping):

    -> grouping.getImports():

​ 对deferredImports中每个DeferredImportSelectorHolder:使用绑定的group进行:

group.process(holder.getMetadata(),holder.getImportSelector())

​ 主要作用就是getAutoConfigurationEntry,获取spring。factories文件中自动配置类并保存到 entries中

​ 最后返回group.selectImports(),主要会通过配置文件中的条件进行过滤,这里返回的是Entry条目集合,最终每个条目结构为:image-20				230505213518197

对每个条目调用processImports进行处理,一般配置类只是个普通配置类,就会走processConfigurationClass这个方法进行处理

标签:bd,configClass,BeanDefination,处理,Spring,配置,源码,注解,解析
From: https://www.cnblogs.com/levry/p/17436673.html

相关文章

  • Spring boot+vue打包、上传宝塔面板并配置https
    终于把网站搞完了,也终于能够通过域名访问了,这次就简单回顾一下这么多时间的经历,总结一下。项目地址穆音博客,本文发布原地址在Springboot+vue打包、上传宝塔面板并配置https我的开发环境是前端使用vue-admin-template,后端使用Springboot+mybatis-plus,由于我要根据后端打包的效......
  • Java 进阶 - SpringJPA 持久层框架
    参考资料https://spring.io/projects/spring-data-jpa介绍SpringDataJPA是Spring基于ORM(ObjectRelationalMapping)框架、JPA规范的基础上封装的一套JPA应用框架,底层使用了Hibernate的JPA技术实现,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了......
  • WPF入门实例 WPF完整例子 WPF DEMO WPF学习完整例子 WPF实战例子 WPF sql实例应用 WPF
    WPF和WinForms都是用于创建Windows桌面应用程序的开发框架,它们有一些相似之处,但也有很多不同之处。在开发速度方面,这取决于具体情况。如果您熟悉WinForms开发并且正在开发简单的界面应用程序,则可能会比使用WPF更快速地完成任务。然而,在设计和实现复杂的用户界面时,WPF可......
  • SpringMVC —— 关于获取请求参数的注解
    1、@RequestParam的3个作用?①起别名②设置默认值③给list集合赋值2、@RequestParam、@RequestBody、@PathVariable分别用于获取什么样格式的请求数据??号传值的参数json对象格式参数路径传值参数......
  • java基于springboot+vue时间管理系统、日记管理系统,附源码+数据库+lw文档+PPT
    1、项目介绍本次设计任务是要设计一个时间管理系统,通过这个系统能够满足时间管理的管理功能。系统的主要功能包括首页,个人中心,系统公告管理,用户管理,时间分类管理,事件数据管理,目标数据管理,用户日记管理等功能。管理员可以根据系统给定的账号进行登录,登录后可以进入时间管理系统,对......
  • SpringMVC-04数据处理及跳转
    SpringMVC参数接收处理和结果跳转处理1结果跳转方式1.1ModelAndView设置ModelAndView对象,根据view的名称,和视图解析器跳到指定的页面.**页面:**{视图解析器前缀}+viewName+{视图解析器后缀}<!--视图解析器--><beanclass="org.springframework.web.servle......
  • python md5源码
    importbinasciiimportsysimportos.pathSV=[0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,0xa679438e,0x49b40......
  • ThreadLocal源码学习笔记
    系列文章目录和关于我一丶ThreadLocal结构#每一个Thread对象都有一个名为threadLocals类型为ThreadLocal.ThreadLocalMap的属性,ThreadLocal.ThreadLocalMap对象内部存在一个Entry数组,其中存储的Entry对象key是ThreadLocal,value便是我们绑定在线程上的值。ThreadLocal可以做......
  • Spring6 探析之@PropertySource 注解
    Spring6探析之@PropertySource注解介绍@PropertySource注解用于加载配置类,在使用Spring时,我们可以使用@PropertySource注解将自定义的配置文件加载到Spring中,方便我们的自定义的开发下面是@PropertySource的源码@Target(ElementType.TYPE)@Retention(RetentionPol......
  • 什么是spring以及相关
    参考:https://www.bilibili.com/video/BV1jc411j7u5/?spm_id_from=333.788.recommend_more_video.0&vd_source=46d50b5d646b50dcb2a208d3946b1598......