首页 > 其他分享 >BeanFactory的总结

BeanFactory的总结

时间:2023-01-19 16:34:20浏览次数:51  
标签:总结 BeanFactory Bean 接口 bean 注册 注解

BeanFactory

BeanFactory是Spring容器中的一个基本类也是很重要的一个类是Spring容器中的一个基本类也是很重要的一个类,在BeanFactory中可以创建和管理Spring容器中的Bean,它对于Bean的创建有一个统一的流程。

Spring的本质是一个bean工厂(beanFactory)或者说bean容器,它按照我们的要求,生产我们需要的各种各样的bean,提供给我们使用。
只是在生产bean的过程中,需要解决bean之间的依赖问题,才引入了依赖注入(DI)这种技术。也就是说依赖注入是beanFactory生产bean时为了解决bean之间的依赖的一种技术而已。

beanFactory会在bean的生命周期的各个阶段中对bean进行各种管理,并且spring将这些阶段通过各种接口暴露给我们,让我们可以对bean进行各种处理,我们只要让bean实现对应的接口,
那么spring就会在bean的生命周期调用我们实现的接口来处理该bean.

在介绍BeanFactory前,我们先想一个问题。我们都知道BeanFactory主要的内容是帮我们生成Bean信息和管理Bean信息,那么我们在xml文件中属性的时候。Spring是如何帮我们生成Bean的呢

BeanDefinitionReader

从xml文件、类路径下使用了@Component系列注解的类、或者从@Configuration注解的配置类,获取BeanDefintiions,然后注册到BeanFactory中。

我们通过BeanDefinitionReader从不同的方式,获取BeanDefintiions Bean的元数据。

那么BeanDefintiions是什么?

    	protected AbstractBeanDefinition(BeanDefinition original) {
    		setParentName(original.getParentName());
    		setBeanClassName(original.getBeanClassName());
    		setScope(original.getScope());
    		setAbstract(original.isAbstract());
    		setFactoryBeanName(original.getFactoryBeanName());
    		setFactoryMethodName(original.getFactoryMethodName());
    		setRole(original.getRole());
    		setSource(original.getSource());
    		copyAttributesFrom(original);
             。。。。。。省略
    }

从上面的代码我们大致的看出。BeanDefintiions其实就是对Bean的一些元数据定义,包括parenName 父类名称 baenClassName:类名,scope bean的作用域。Abstract是否是抽象的等信息。
通过 BeanDefinitionReader获取到BeanDefinition之后 。我们在通过BeanDefinitionRegistry将beanDefinition注册到BeanFacory中。存储在BeanFactory的一个conCurrentHashMap中。key为beanName,Value就是BeanDefinition元数据。
那么获取Bean就从conCurrentHashMap中通过BeanName获取对应的Bean信息。

从上面的分析:我们可以看到Bean的加载解析过程如下图所示:

接下来我们针对BeanDefinitionReader、BeanDefinitionRegistry、BeanFactory分别分析:

BeanDefinitionReader

  1. XmlBeanDefinitionReader:基于XML文件
    读取解析xml文件,通过Parser解析xml文件的标签。
    针对beans标签,生成对应的BeanDefintions,然后注册到BeanFactory中。
    针对其他有特殊功能的标签,如context:component-scan,context:anotation-config,还可以生成BeanFactoryPostProcessor,BeanPostProcessor接口实现类的bean等;除了可以生成BeanDefinitions之外,还可以实现其他功能。NamespaceHandler:XML标签名称空间处理器
    被XmlBeanDefinitionReader使用,XmlBeanDefinitionReader在处理每个XML标签名称空间的时候,如applicationContext.xml的context:,mvc:,通过一个DefaultNamespaceHandlerResolver来获取对应的NamespaceHandler实现类,然后通过这个NamespaceHandler实现类,进一步获取该命名空间的内部标签对应的BeanDefinitionParser实现类。

被XmlBeanDefinitionReader使用,专门用于处理xml文件的beans标签的标签处理器。即XmlBeanDefinitionReader读取xml文件,创建Document对象,然后交给BeanDefinitionDocumentReader处理。BeanDefinitionDocumentReader解析Document对象的Element节点,然后创建BeanDefinitions集合,通过XmlBeanDefinitionReader注册到XmlBeanDefinitionReader所在的BeanFactory。

  1. AnnotatedBeanDefinitionReader:注册指定的类列表annotatedClasses
    可以使用编程方法,显示指定将哪些类需要注册到BeanFactory。
    主要是被AnnotationConfigApplicationContext使用,即基于注解配置的ApplicationContext,这是SpringBoot的默认ApplicationContext。典型使用为:先获取所有使用了@Configuration注解的类,然后通过AnnotatedBeanDefinitionReader生成与这些类对应的BeanDefinitions,并注册到BeanFactory。

  2. ClassPathBeanDefinitionScanner:注册指定的basePackages下面的类
    扫描指定类路径(包)下面的类,检测是否存在@Component注解及其子注解,从而生成BeanDefinition,然后注册到BeanFactory。没有实现BeanDefinitionReader接口,但基于相同的设计思路:BeanDefinitionReader。与AnnotatedBeanDefinitionReader一样,都是获取指定类,生成该类的BeanDefinition注册到BeanFactory,而不是像xml文件一样已经通过bean标签显示说明这个就是bean。也是主要是被AnnotationConfigApplicationContext使用。与其他两种也是基于basePackages类路径扫描的方式不同之处为:context:component-scan标签:基于XML的ApplicationContext,实现类路径扫描,底层使用ComponentScanBeanDefinitionParser这个parser来处理。@ComponentScan:对于处理@Configuration配置类上面的@ComponentScan注解,则是通过ComponentScanAnnotationParser来处理的。

  3. ConfigurationClassBeanDefinitionReader:基于@Configuration注解的类配置
    处理@Configuration注解的配置类,加在这些配置类上面的注解,即与@Configuration一起使用的注解,如@ComponentScan,@PropertySource,@Import,@Profile等。
    ConfigurationClassBeanDefinitionReader主要被ConfigurationClassPostProcessor调用,ConfigurationClassPostProcessor为BeanFactoryPostProcessor

BeanDefinitionRegistry

注册BeanDefinitions。提供registerBeanDefinition,removeBeanDefinition等方法,用来从BeanFactory注册或移除BeanDefinition。
通常BeanFactory接口的实现类需要实现这个接口。
实现类(通常为BeanFactory接口实现类)的对象实例,被DefinitionReader接口实现类引用,DefinitionReader将BeanDefintion注册到该对象实例中。

除了上述的BeanDefinitionRegisry还有一个负责单例Bean注册的接口:SingletonBeanRegistry

用于注册单例Bean对象实例,实现类定义存储Bean对象实例的map,BeanFactory的类层次结构中需要实现这个接口,来提供Bean对象的注册和从Bean对象实例的map获取bean对象。

BeanFactory

接口具体实现类

  1. DefaultListableBeanFactory

BeanFactory接口体系的默认实现类,实现以上接口的功能,提供BeanDefinition的存储map,Bean对象对象的存储map。

其中Bean对象实例的存储map,定义在FactoryBeanRegistrySupport,FactoryBeanRegistrySupport实现了SingletonBeanRegistry接口,而DefaultListableBeanFactory的基类AbstractBeanFactory,继承于FactoryBeanRegistrySupport。

  1. StaticListableBeanFactory

用于存储给定的bean对象实例,不支持动态注册功能,是ListableBeanFactory接口的简单实现。

beanFactoty后置处理器: BeanFactoryPostProcessor

benFactoryPostProCessor是BeanFactory的后置处理器:

在BeanFactory创建好,加载好其所包含的所有beanDefinitions,但是还没有实例化bean之前,执行,具体为调用postProcessBeanFactory方法。

  1. 加载更多的bean元数据
    ConfigurationClassPostProcessor,用于从BeanFactory中检测使用了@Configuration注解的类,对于这些类对应的BeanDefinitions集合,遍历并依次交给ConfigurationClassParser,ConfigurationClassBeanDefinitionReader处理,分别是处理与@Configuration同时使用的其他注解和将类内部的使用@Bean注解的方法,生成BeanDefinition,注册到BeanFactory。

  2. 对bean元数据进行加工处理
    BeanDefinition属性填充、修改:在postProcessBeanFactory方法中,可以对beanFactory所包含的beanDefinitions的propertyValues和构造函数参数值进行修改,如使用PropertyPlaceHolderConfigurer来对BeanDefinition的propertyValues的占位符进行填充、赋值。或者使用PropertyResourceConfigurer获取config文件中属性,对BeanDefinitions的相关属性进行赋值或者值覆盖。

bean对象后置处理器:BeanPostProcessor

Bean后置处理器:负责对已创建好的bean对象进行加工处理。

主要是可以对新创建的bean实例进行修改,提供了一个类似于hook机制,对创建好的bean对象实例进行修改。

核心方法
postProcessBeforeInitialization:在创建好bean实例,但是在任何初始化回调执行之前,如InitializingBean的afterPropertiesSet,先执行该方法。

postProcessAfterInitialization:在创建好bean实例,并且所有的初始化回调都执行完了,如InitializingBean的afterPropertiesSet,再执行该方法。

标签:总结,BeanFactory,Bean,接口,bean,注册,注解
From: https://www.cnblogs.com/lori/p/17061725.html

相关文章

  • 2022年总结
    临近年关,辞旧迎新,开年计划年年做,能否执行到头是个问题,善始者众,善终者寡,这篇就对今年做个了结。成长方法论慢即是快现在搜索引擎很方便,碰到了随手一查就好了,尤其是今年还......
  • OpenMP 环境变量使用总结
    OpenMP环境变量使用总结OMP_CANCELLATION,在OpenMP规范4.5当中规定了取消机制,我们可以使用这个环境变量去设置是否启动取消机制,如果这个值等于TRUE那么就是开启线......
  • 网络编程知识总结
    网络编程1、概述计算机网络:计算机网络是指将​​地理​​​位置不同的具有独立功能的多台​​计算机​​​及其外部设备,通过通信线路连接起来,在​​网络操作系统​​​,​​......
  • Java知识总结,不止为了秋招(上)!!!
    文章目录​​1、Java基础​​​​2、Java进阶​​​​3、数据库​​​​4、前端​​​​5、JavaWeb​​​​6、SSM框架​​​​7、JVM​​​​8、SpringBoot框架​​​​9......
  • 2022年终总结
    曾经的日子一去不复返了。我希望我的未来可以不用再悲伤下去。有什么想做的就尽情去做!我爱这个世界美好的事物。我想与人参与、创造这个世界美好的事物,我想要将这个世......
  • 一个想活得简单的程序猿的2022年终总结!
    前言今年的总结相比以往来说,可写的太少了,但看到我17年开始写的年终总结,已定下每年写下的承诺,因此即便可写的不多,但是还是写下吧,毕竟又过了一年,总有东西会留下!今年事件......
  • 2023.1.2~2023.1.18 学习总结
    这一段时间学的东西还是蛮多的,所以稍微总结一下左偏树左偏树是堆的一种,具有堆的性质,同时支持快速合并,所以也被称为可并堆。先来看一些定义:我们把一个左子树或右子树为......
  • CSS3选择器总结(表格)
    CSS3选择器总结(表格)html标签有2种关系:包含关系和并列关系;CSS3选择器分类:基本选择器、组合选择器、属性选择器、伪类选择器;伪类选择器分类:动态伪类、结构伪类、状态伪类......
  • 「学习笔记」莫比乌斯反演套路总结
    基本套路Crash的数字表格/JZPTAB求:\[\sum_{i=1}^n\sum_{j=1}^m\mathrm{lcm}(i,j)\]\[\begin{aligned}&\sum_{i=1}^n\sum_{j=1}^m\mathrm{lcm}(i,j)\\=&\sum_{i=......
  • 寒假题目总结
    Strangedevice题目大意这是一道交互题,你需要猜出一个\(n\)个点的树。你可以作出\(\leq80\)次如下询问:给交互库一个序列\(d_1,d_2,\ldots,d_n\),交互库会返回一......