• 【Spring容器的启动过程】


    Spring容器的启动过程

    Spring 在初始化过程中有二个非常重要的步骤,容器的初始化与刷新。

    初始化流程

    在这里插入图片描述

    • 如果想生成 bean 对象,那么就需要一个 beanFactory 工厂(DefaultListableBeanFactory)
    • 如果想让加了特定注解(如 @Service、@Repository)的类,进行读取,转化成 BeanDefinition 对象(BeanDefinition存储了 bean 对象的所有特征信息,如是否单例,是否懒加载,factoryBeanName 等),那么就需要一个注解配置读取器(AnnotatedBeanDefinitionReader)
    • 如果想对用户指定的包目录进行扫描查找 bean 对象,就需要一个路径扫描器(ClassPathBeanDefinitionScanner)

    在加载配置文件时,Spring会创建一个BeanFactory工厂,然后使用配置信息填充该工厂的BeanDefinition,根据这些信息创建相关的Bean实例。在创建Bean实例时,Spring采用了延迟初始化的策略,即只有当需要使用Bean实例时才会进行初始化。

    注册BeanDefinition的流程主要包括解析配置文件、扫描注解、解析Java Config等。在解析配置文件时,Spring会根据配置文件的语法规则进行解析,并将解析结果封装成BeanDefinition对象。在扫描注解时,Spring会扫描指定包下的类,并将带有指定注解的类封装成BeanDefinition对象。在解析Java Config时,Spring会根据Java Config配置文件的语法规则进行解析,并将解析结果封装成BeanDefinition对象。

    ClassPathBeanDefinitionScanner是Spring框架的一个工具类,它可以在指定的包路径下搜索bean。它会扫描所有符合条件的类,并将其注册为bean,以便在后续的操作中使用。使用这个工具类,会先创建一个BeanDefinitionRegistry对象,然后创建一个ClassPathBeanDefinitionScanner对象,并设置它的扫描路径和过滤器。最后,调用scan方法开始扫描,扫描完成后,ClassPathBeanDefinitionScanner会自动将扫描到的类注册到BeanDefinitionRegistry中。完成注册后,你就可以使用Spring的BeanFactory来获取指定的bean了。

    刷新流程

    在这里插入图片描述
    refresh()主要用于容器的刷新,Spring中的每一个容器都会调用refresh()方法进行刷新。refresh()方法主要完成以下几个步骤:

    (1)进行容器的准备工作,如初始化环境变量、注册系统事件监听器等。

    (2)创建或获取BeanFactory实例。如果创建时传入了BeanFactory实例,则使用该实例;否则,根据配置文件创建一个新的BeanFactory实例。

    (3)对BeanFactory进行一些必要的设置,如设置ClassLoader、设置BeanPostProcessor等。

    (4)对BeanFactory进行后置处理,可用于扩展BeanFactory的功能。

    (5)执行BeanFactoryPostProcessor接口的实现类,对BeanFactory进行后置处理。

    (6)注册所有的BeanPostProcessor实现类。

    (7)初始化MessageSource,用于国际化处理。

    (8)初始化事件广播器,用于事件的发送和接收。

    (9)通知所有已注册的监听器容器已经初始化完成。

    (10)关闭容器时进行资源的释放。

    (11)注册事件监听器。

    (12)完成BeanFactory的初始化工作,包括创建实例、注入依赖、执行初始化方法等。

    (13)完成容器的初始化,释放资源等。

    //refresh()的简略源码:
    public void refresh() throws BeansException, IllegalStateException {
    	synchronized (this.startupShutdownMonitor) {
    		// 1. 刷新前的预处理
    		prepareRefresh();
    		// 2. 获取 beanFactory,即前面创建的【DefaultListableBeanFactory】
    		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    		// 3. 预处理 beanFactory,向容器中添加一些组件
    		prepareBeanFactory(beanFactory);
    		try {
    			// 4. 子类通过重写这个方法可以在 BeanFactory 创建并与准备完成以后做进一步的设置
    			postProcessBeanFactory(beanFactory);
    			// 5. 执行 BeanFactoryPostProcessor 方法,beanFactory 后置处理器
    			invokeBeanFactoryPostProcessors(beanFactory);
    			// 6. 注册 BeanPostProcessors,bean 后置处理器
    			registerBeanPostProcessors(beanFactory);
    			// 7. 初始化 MessageSource 组件(做国际化功能;消息绑定,消息解析)
    			initMessageSource();
    			// 8. 初始化事件派发器,在注册监听器时会用到
    			initApplicationEventMulticaster();
    			// 9. 留给子容器(子类),子类重写这个方法,在容器刷新的时候可以自定义逻辑,web 场景下会使用
    			onRefresh();
    			// 10. 注册监听器,派发之前步骤产生的一些事件(可能没有)
    			registerListeners();
    			// 11. 初始化所有的非单实例 bean
    			finishBeanFactoryInitialization(beanFactory);
    			// 12. 发布容器刷新完成事件
    			finishRefresh();
    		}
    		catch(){...}
            finally{...}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
  • 相关阅读:
    VS Code使用node.js编译,代码自动补全方法
    【Java】我的第一个入门程序HelloWorld以及认识变量和常量
    Elasticsearch
    小程序day04
    python的脚本如何执行
    js dispatchEvent派发自定义事件
    excel提取单元格中的数字
    高数---二重积分
    大数据软件项目的验收流程
    1.2、因特网概述
  • 原文地址:https://blog.csdn.net/java_wxid/article/details/132888465