Spring中的BeanFactory工厂详细解析

 更新时间:2023年12月05日 08:49:39   作者:遇见更好的自己、  
这篇文章主要介绍了Spring中的BeanFactory工厂详细解析,Spring的本质是一个bean工厂(beanFactory)或者说bean容器,它按照我们的要求,生产我们需要的各种各样的bean,提供给我们使用,需要的朋友可以参考下

BeanFactory

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文件中<baen>属性的时候。

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。  

2. AnnotatedBeanDefinitionReader

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

3. 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来处理的。

4. 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。

2. 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加载过程全部分析完成:

到此这篇关于Spring中的BeanFactory工厂详细解析的文章就介绍到这了,更多相关BeanFactory工厂内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • alibaba seata服务端具体实现

    alibaba seata服务端具体实现

    seata是来处理分布式服务之间互相调用的事务问题,本文重点给大家介绍alibaba-seata实现方法,文中通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02
  • Java微信公众号推送模版消息的步骤示例详解

    Java微信公众号推送模版消息的步骤示例详解

    模板消息是一种向用户发送通知的服务,广泛用于订单状态更新、服务提醒等场景,下面,我将详细介绍如何使用Java结合微信官方提供的API来实现模板消息的推送,感兴趣的朋友跟随小编一起看看吧
    2024-08-08
  • SpringBoot整合MybatisPlus的基本应用详解

    SpringBoot整合MybatisPlus的基本应用详解

    MyBatis-Plus (简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为 简化开发、提高效率而生,本文将给大家介绍一下SpringBoot整合MybatisPlus的基本应用,需要的朋友可以参考下
    2024-05-05
  • Java Semaphore信号量使用分析讲解

    Java Semaphore信号量使用分析讲解

    Semaphore实际上是一种共享锁,因为它允许多个线程并发获取共享的资源,在Semaphore对象创建时必须设置可用令牌的初始数量permits,用于控制并发时同时获取资源权限的线程数量,这篇文章主要介绍了Java中的Semaphore如何使用,需要的朋友可以参考下
    2022-12-12
  • java中的Io(input与output)操作总结(一)

    java中的Io(input与output)操作总结(一)

    所谓IO,也就是Input与Output的缩写。在java中,IO涉及的范围比较大,这里主要讨论针对文件内容的读写,感兴趣的朋友可以了解下
    2013-01-01
  • Java基础之Bean的创建、定位和使用

    Java基础之Bean的创建、定位和使用

    这篇文章主要介绍了Java基础之Bean的创建、定位和使用,文中有非常详细的图文示例及代码,对正在学习java基础的小伙伴们有很好地帮助,需要的朋友可以参考下
    2021-05-05
  • springboot之端口设置和contextpath的配置方式

    springboot之端口设置和contextpath的配置方式

    这篇文章主要介绍了springboot之端口设置和contextpath的配置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • 全面解析Java中的GC与幽灵引用

    全面解析Java中的GC与幽灵引用

    一般的应用程序不会涉及到 Reference 编程, 但是了解这些知识会对理解 GC 的工作原理以及性能调优有一定帮助,在实现一些基础性设施比如缓存时也可能会用到,希望本文能有所帮助
    2013-09-09
  • SpringBoot中的@Component注解源码

    SpringBoot中的@Component注解源码

    在SpringBoot中,@Component注解用于标识一个类为Bean,并由Spring进行管理,它需要配合@ComponentScan注解使用,后者负责扫描包含@Component的类,并进行自动装配,本文给大家介绍SpringBoot中的@Component注解源码,感兴趣的朋友一起看看吧
    2024-01-01
  • java微信公众号支付示例详解

    java微信公众号支付示例详解

    这篇文章主要为大家详细介绍了java微信公众号支付示例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12

最新评论