spring中的bean

spring中的bean

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、一些基本概念

「Spring是一个IOC容器」

当我们不用Spring进行开发时,我们需要在代码中设置对象的依赖关系。当我们用了Spring之后,由Spring来管理这种依赖关系,当我们想使用对象时,直接从Spring容器中获取即可

「BeanDefinition」

在Spring中对象被叫做Bean,因为Spring Bean在Java类的基础上增加了很多概念,比如scope(作用域),isLazyInit(是否延迟初始化),isSingleton(是否单例),此时Java类不能完整的描述,所以需要新的定义描述类,这个类就是BeanDefinition

「BeanDefinitionReader」

BeanDefinitionReader会将配置的bean解析成为BeanDefinition,Spring Bean的配置方式有很多种,如XML,properties,groovy,注解(可能通过properties,groovy的方式你不常用,但Spring确实支持这种方式),所以BeanDefinitionReader的实现类也很多

「ClassPathBeanDefinitionScanner」

当把Bean配置出后,得需要相应的组件把他们从资源文件中扫描出来吗,这个组件就是ClassPathBeanDefinitionScanner

「BeanDefinitionRegistry」

BeanDefinitionReader将配置的bean解析成为BeanDefinition,需要将BeanDefinition保存到BeanDefinitionRegistry。类似工厂把原料保存到仓库中,供后续生产产品使用

「BeanFactory」

BeanFactory会根据BeanDefinition将Bean生产出来,并保存下来

「DefaultListableBeanFactory」

DefaultListableBeanFactory在绝大多数的场景都是BeanFactory的实现类,DefaultListableBeanFactory实现了BeanDefinitionRegistry接口和BeanFactory接口,所以能保存Bean定义,同时又能根据Bean定义将Bean生产出来

「BeanPostProcessor」

BeanFactory根据BeanDefinition生成Bean的过程是一个标准化的流程,就像一个流水线一样,当然你可以在这个流水线上做一些自定义的操作。「在Spring中你可以通过实现BeanPostProcessor来干预Bean的生产过程」

「BeanFactoryPostProcessor」

Spring作为一个强大的容器,不仅能让你干预Bean的生产过程,还可以让你干预BeanFactory,「例如你可以通过BeanFactoryPostProcessor将Bean的作用域都该成原型,默认是单例」

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、Spring容器启动流程

我们常用的容器有如下2种

  • 基于xml配置Bean(ClassPathXmlApplicationContext)
  • 基于注解配置Bean(AnnotationConfigApplicationContext)

「另外需要注意的一点是,在容器初始化的过程中注册了6个Bean」

  • ConfigurationClassPostProcessor(「实现了BeanFactoryPostProcessor,处理@Configuration,@ComponmentScan等注解,这是一个很重要的类」)
  • 「AutowiredAnnotationBeanPostProcessor(实现了BeanPostProcessor,处理@Autowired,@Value等)」
  • 「CommonAnnotationBeanPostProcessor(实现了BeanPostProcessor,用来处理JSR-250规范的注解,如@Resource,@PostConstruct等)」
  • PersistenceAnnotationBeanPostProcessor(实现了BeanFactoryPostProcessor,用来支持JPA,在我们这个Demo中不会注册,因为路径中没有JPA相关的类)
  • EventListenerMethodProcessor(实现了BeanFactoryPostProcessor)
  • DefaultEventListenerFactory
    注册的过程估计你也猜到了,就是将对应的类,如ConfigurationClassPostProcessor解析为RootBeanDefinition,并注册到BeanDefinitionRegistry中

1容器刷新过程

「容器刷新的过程可以细分为如下几个步骤」

  1. Spring应用上下文启动准备阶段
  2. BeanFactory创建阶段
  3. BeanFactory准备阶段
  4. BeanFactory后置处理阶段
  5. BeanFactory注册BeanPostProcessor阶段
  6. 初始化内建Bean:MessageSource
  7. 初始化内建Bean:Spring事件广播器
  8. Spring应用上下文刷新阶段
  9. Spring事件监听器注册阶段
  10. BeanFactory初始化完成阶段
  11. Spring应用上下文启动完成阶段

Spring应用上下文启动准备阶段

AbstractApplicationContext#prepareRefresh

  1. 记录启动时间 startupDate
  2. 设置标志为closed(false),active(true)
  3. 初始化PropertySources
  4. 校验Environment中必须属性
  5. 初始化事件监听器集合
  6. 初始化早期Spring事件集合

BeanFactory创建阶段

AbstractApplicationContext#obtainFreshBeanFactory

刷新Spring应用上下文底层BeanFactory(refreshBeanFactory)

  1. 如果已存在BeanFactory,销毁Bean,并且关闭BeanFactory
  2. 创建DefaultListableBeanFactory(一般情况下都是DefaultListableBeanFactory)
  3. 设置BeanFactory id
  4. 设置BeanFactory是否允许BeanDefinition重复定义,是否允许循环引用 加载BeanDefinition
  5. 关联新建的BeanFactory到Spring应用上下文
  6. 返回Spring应用上下文底层BeanFactory(getBeanFactory)

BeanFactory准备阶段

AbstractApplicationContext#prepareBeanFactory

  1. 关联ClassLoader
  2. 设置Bean表达式处理器
  3. 添加 PropertyEditorRegistrar 的实现 ResourceEditorRegistrar
  4. 「注册BeanPostProcessor(ApplicationContextAwareProcessor)」,用来处理Aware回调接口
  5. 忽略Aware回调接口作为依赖注入接口
  6. 注册ResolvableDependency对象-BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext
  7. 「注册BeanPostProcessor(ApplicationListenerDetector)」,用来处理ApplicationListener接口
  8. 注册BeanPostProcessor(LoadTimeWeaverAwareProcessor),用来处理aop
  9. 注册单例对象(Environment,Java System Properties以及OS环境变量)

BeanFactory后置处理阶段

如果想对BeanFactory进行扩展,可以通过如下2种方式

  1. 子类重写AbstractApplicationContext#postProcessBeanFactory方法

  2. 实现BeanFactoryPostProcessor接口

AbstractApplicationContext#invokeBeanFactoryPostProcessors 方法就是用来处理BeanFactoryPostProcessor接口的,调用的次序比较复杂,总结如下

  1. BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(入参中的)
  2. BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(容器中的,并且实现了PriorityOrdered接口)
  3. BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(容器中的,并且实现了Ordered接口)
  4. BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(容器中的,除去第2,3步剩余的BeanDefinitionRegistryPostProcessor)
  5. BeanDefinitionRegistryPostProcessor#postProcessBeanFactory(所有BeanDefinitionRegistryPostProcessor接口实现类)
  6. BeanFactoryPostProcessor#postProcessBeanFactory(入参数中的)
  7. BeanFactoryPostProcessor#postProcessBeanFactory(容器中的,实现了PriorityOrdered接口)
  8. BeanFactoryPostProcessor#postProcessBeanFactory(容器中的,实现了Ordered接口)
  9. BeanFactoryPostProcessor#postProcessBeanFactory(容器中的,除去7,8步剩余的BeanFactoryPostProcessor)

「注册BeanPostProcessor

(ConfigurationClassPostProcessor.ImportAwareBeanPostProcessor)」

注册LoadTimeWeaverAwareProcessor对象

前面说过在容器初始化的过程中,往容器中注入了一个BeanFactoryPostProcessor接口的实现类即ConfigurationClassPostProcessor。

「这是一个非常重要的BeanFactoryPostProcessor,通过@Bean、@Component、@ComponentScan、@Import、@ImportResource注入Bean的方式都由这个类来处理,对这些注解的实现感兴趣的小伙伴可以看一下这个类的源码」

「回调BeanFactoryPostProcessor接口的相关方法就搞这么多排序规则,有必要吗?」

有必要,一方面是提高可扩展性,另外一方面是有些实现类的调用优先级必须要高一点,不然会有问题,我后面用例子演示

BeanFactory注册BeanPostProcessor阶段

  1. 「注册BeanPostProcessor

    (PostProcessorRegistrationDelegate.BeanPostProcessorChecker)」

  2. 注册PriorityOrdered类型的BeanPostProcessor

  3. 注册Ordered类型的BeanPostProcessor

  4. 注册普通的BeanPostProcessor

  5. 注册MergedBeanDefinitionPostProcessor

  6. 「注册BeanPostProcessor(ApplicationListenerDetector)」

「此时注册到容器中的BeanPostProcessor有如下6个(注册的时机我都在前文标注过了)」,这6个BeanPostProcessor在Spring Bean的生命周期中起着重要的作用,这个注册时机会影响后面调用的时机,所以搞优先级很有必要

初始化内建Bean:MessageSource

AbstractApplicationContext#initMessageSource 国际化相关的内容,不怎么用,不研究了

初始化内建Bean:Spring事件广播器

AbstractApplicationContext#initApplicationEventMulticaster

Spring应用上下文刷新阶段

AbstractApplicationContext#onRefresh 留给子类扩展用的

Spring事件监听器注册阶段

AbstractApplicationContext#registerListeners

  1. 添加当前应用上下文所关联的ApplicationListener对象
  2. 添加BeanFactory所注册的ApplicationListener
  3. 广播早期Spring事件

BeanFactory初始化完成阶段

AbstractApplicationContext#finishBeanFactoryInitialization

  1. conversionService如果存在的话,设置到beanFactory
  2. 添加 StringValueResolver 对象
  3. 依赖查找LoadTimeWeaverAware Bean
  4. beanFactory将ClassLoader临时设置为null
  5. beanFactory冻结配置
  6. 「beanFactory初始化非延迟单例Beans」

「说一个高频面试题,Spring容器在何时创建对象?」

  1. scope=singleton,容器启动过程中创建对象
  2. scope!=singleton,延迟Bean(加了@Lazy,或),在调用getBean的同时创建对象

Spring应用上下文启动完成阶段

AbstractApplicationContext#finishRefresh

  1. 清除ResoureLoader缓存
  2. 初始化lifecycleProcessor对象
  3. 调用lifecycleProcessor#onRefresh方法
  4. 发布应用上下文刷新事件 ContextRefreshedEvent
  5. 向MBeanServer托管Live Beans

Spring Bean生命周期

BeanFactoryPostProcessor和BeanPostProcessor
「书接上文,如果我们要对Spring进行扩展,一般有如下方法」

  1. 实现BeanFactoryPostProcessor接口
  2. 实现BeanPostProcessor接口

「Spring Bean的生命周期可以主要分为如下4个部分」

  1. 处理BeanDefinition:BeanDefinition的解析,注册,合并
  2. Bean实例化(Instantiation):还没有生成bean,即没有调用构造函数,生成对象
  3. Bean初始化(Initialization):已经生成bean,进行属性赋值
  4. Bean销毁:并没有gc

「分享到这了,我就抛出一个问题,BeanFactoryPostProcessor和BeanPostProcessor接口哪个先执行?」

当然是BeanFactoryPostProcessor先执行,BeanPostProcessor后执行了,仔细看启动流程图

  1. BeanFactoryPostProcessor的执行在BeanFactory后置处理阶段
  2. BeanPostProcessor的执行在BeanFactory初始化完成阶段(初始化非延迟单例Bean)

总结

可以看到在整个Bean的生命周期中,各种BeanPostProcessor起了非常重要的作用,搞懂了这些BeanPostProcessor的实现,基本上就搞懂了Spring Bean的生命周期

不仅如此,BeanPostProcessor不仅在IOC上发挥了重要作用,在AOP上也发挥了重要的作用

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值