服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - 揭秘Spring容器创建与启动:从零到运行的全过程

揭秘Spring容器创建与启动:从零到运行的全过程

2023-12-28 14:56一安未来 Java教程

在Spring中,Bean是指由Spring容器管理的对象。这些对象通常是应用程序的组件,如服务、数据访问对象(DAO)、实体等。Bean由Spring容器负责实例化、组装和管理

前言

Spring以其强大的IOC(控制反转)和依赖注入功能而闻名,Bean的加载流程是整个应用程序初始化的核心步骤之一,它涉及到一系列的生命周期过程和初始化的步骤,确保Bean被正确地配置、依赖注入,并且能够以可预测的方式运行。

配置方式有:

  • 基于XML方式
  • 基于注解方式

基础概念

  • Bean:在Spring中,Bean是指由Spring容器管理的对象。这些对象通常是应用程序的组件,如服务、数据访问对象(DAO)、实体等。Bean由Spring容器负责实例化、组装和管理
  • Spring容器:Spring容器是一个负责创建、配置和管理Bean的容器。主要有两种容器:BeanFactory和ApplicationContext。BeanFactory提供了基本的DI(依赖注入)功能,而ApplicationContext是BeanFactory的扩展,提供了更多的企业级功能,例如事件传播、AOP、国际化等。
  • BeanPostProcessor:BeanPostProcessor是一个接口,允许在Bean实例化和初始化过程中插入自定义的处理逻辑。通过实现该接口,开发者可以在Bean初始化前后执行额外的逻辑操作。

正文

演示代码

@ComponentScan("org.yian.bean")
@Configuration
public class BeanConfig {

    @Bean
    public Test test(){
        return new Test();
    }
}
@Test
public void test03(){
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);

    applicationContext.close();
}

初始化

重点关注 refresh() 方法,该方法实际是调用的父类 AbstractApplicationContext 的方法:

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this();
    this.register(componentClasses);
    this.refresh();
}
public void refresh() throws BeansException, IllegalStateException {
    synchronized(this.startupShutdownMonitor) {
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
        this.prepareRefresh();
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
        this.prepareBeanFactory(beanFactory);

        try {
            this.postProcessBeanFactory(beanFactory);
            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
            this.invokeBeanFactoryPostProcessors(beanFactory);
            this.registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();
            this.initMessageSource();
            this.initApplicationEventMulticaster();
            this.onRefresh();
            this.registerListeners();
            this.finishBeanFactoryInitialization(beanFactory);
            this.finishRefresh();
        } catch (BeansException var10) {
            if (this.logger.isWarnEnabled()) {
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
            }

            this.destroyBeans();
            this.cancelRefresh(var10);
            throw var10;
        } finally {
            this.resetCommonCaches();
            contextRefresh.end();
        }

    }
}

1.刷新前的预处理:

揭秘Spring容器创建与启动:从零到运行的全过程图片

prepareRefresh():

  • initPropertySources():初始化一些属性设置;子类自定义个性化的属性设置方法;
  • getEnvironment().validateRequiredProperties():检验属性的合法等
  • earlyApplicatinotallow= new LinkedHashSet<ApplicationEvent>():保存容器中的一些早期的事件

2.获取BeanFactory:

揭秘Spring容器创建与启动:从零到运行的全过程图片

obtainFreshBeanFactory()

  • refreshBeanFactory():刷新【创建】BeanFactory

创建了一个this.beanFactory = new DefaultListableBeanFactory()

设置id

  • getBeanFactory():返回刚才GenericApplicationContext创建的BeanFactory对象
  • 将创建的BeanFactory【DefaultListableBeanFactory】返回

3.BeanFactory的预准备工作:

揭秘Spring容器创建与启动:从零到运行的全过程图片

prepareBeanFactory(beanFactory)

  • 设置BeanFactory的类加载器、支持表达式解析器...
  • 添加部分BeanPostProcessor【ApplicationContextAwareProcessor】
  • 设置忽略的自动装配的接口EnvironmentAware、EmbeddedValueResolverAware、xxx
  • 注册可以解析的自动装配,我们能直接在任何组件中自动注入:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
  • 添加BeanPostProcessor【ApplicationListenerDetector】
  • 添加编译时的AspectJ;
  • 给BeanFactory中注册一些能用的组件;
  • environment【ConfigurableEnvironment】
  • systemProperties【Map<String, Object>】
  • systemEnvironment【Map<String, Object>】

4.后置处理工作:

揭秘Spring容器创建与启动:从零到运行的全过程图片

postProcessBeanFactory(beanFactory)

  • 子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置

5.执行BeanFactoryPostProcessor的方法:

揭秘Spring容器创建与启动:从零到运行的全过程图片

invokeBeanFactoryPostProcessors(beanFactory)

  • BeanFactoryPostProcessor:BeanFactory的后置处理器,在BeanFactory标准初始化之后执行的
  • 先执行BeanDefinitionRegistryPostProcessor的方法

获取所有的BeanDefinitionRegistryPostProcessor

先执行实现了PriorityOrdered优先级接口的BeanDefinitionRegistryPostProcessor:postProcessor.postProcessBeanDefinitionRegistry(registry)

再执行实现了Ordered顺序接口的BeanDefinitionRegistryPostProcessor:postProcessor.postProcessBeanDefinitionRegistry(registry)

最后执行没有实现任何优先级或者是顺序接口的BeanDefinitionRegistryPostProcessors:postProcessor.postProcessBeanDefinitionRegistry(registry)

  • 再执行BeanFactoryPostProcessor的方法
  • 获取所有的BeanFactoryPostProcessor

  • 先执行实现了PriorityOrdered优先级接口的BeanFactoryPostProcessor:postProcessor.postProcessBeanFactory()

  • 再执行实现了Ordered顺序接口的BeanFactoryPostProcessor:postProcessor.postProcessBeanFactory()

  • 最后执行没有实现任何优先级或者是顺序接口的BeanFactoryPostProcessor:postProcessor.postProcessBeanFactory()

6.注册BeanPostProcessor:

揭秘Spring容器创建与启动:从零到运行的全过程图片

registerBeanPostProcessors(beanFactory)

  • 获取所有的 BeanPostProcessor,后置处理器都默认可以通过PriorityOrdered、Ordered接口来执行优先级
  • 先注册PriorityOrdered优先级接口的BeanPostProcessor,把每一个BeanPostProcessor添加到BeanFactory中,beanFactory.addBeanPostProcessor(postProcessor)
  • 再注册Ordered接口的
  • 再注册没有实现任何优先级接口的
  • 再注册MergedBeanDefinitionPostProcessor
  • 最后注册一个ApplicationListenerDetector,来在Bean创建完成后检查是否是ApplicationListener,如果是applicationContext.addApplicationListener((ApplicationListener<?>) bean)

7.初始化MessageSource组件:

揭秘Spring容器创建与启动:从零到运行的全过程图片

initMessageSource()

  • 获取BeanFactory
  • 看容器中是否有id为messageSource的,类型是MessageSource的组件,如果有赋值给messageSource,如果没有自己创建一个DelegatingMessageSource【MessageSource:取出国际化配置文件中的某个key的值;能按照区域信息获取】
  • 把创建好的MessageSource注册在容器中,以后获取国际化配置文件的值的时候,可以自动注入MessageSource

8.初始化事件派发器:

揭秘Spring容器创建与启动:从零到运行的全过程图片

  • initApplicationEventMulticaster()
  • 获取BeanFactory
  • 从BeanFactory中获取applicationEventMulticaster的ApplicationEventMulticaster
  • 如果上一步没有配置;创建一个SimpleApplicationEventMulticaster
  • 将创建的ApplicationEventMulticaster添加到BeanFactory中,以后其他组件直接自动注入

9.容器刷新:

揭秘Spring容器创建与启动:从零到运行的全过程图片

  • onRefresh():留给子容器(子类)
  • 子类重写这个方法,在容器刷新的时候可以自定义逻辑

10.注册监听器:

揭秘Spring容器创建与启动:从零到运行的全过程图片

  • registerListeners(),给容器中将所有项目里面的ApplicationListener注册进来;
  • 从容器中拿到所有的ApplicationListener
  • 将每个监听器添加到事件派发器中:getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName)
  • 派发之前步骤产生的事件;

11.初始化所有剩下的单实例bean

揭秘Spring容器创建与启动:从零到运行的全过程图片

  • finishBeanFactoryInitialization(beanFactory)
  • 获取容器中的所有Bean,依次进行初始化和创建对象
  • 获取Bean的定义信息,RootBeanDefinition
  • Bean不是抽象的,是单实例的,是懒加载

判断是否是FactoryBean,是否是实现FactoryBean接口的Bean

不是工厂Bean,利用getBean(beanName)创建对象

检查所有的Bean是否是SmartInitializingSingleton接口的,如果是就执行afterSingletonsInstantiated()

  • getBean(beanName):

揭秘Spring容器创建与启动:从零到运行的全过程图片

  • 先获取缓存中保存的单实例Bean ,如果能获取到说明这个Bean之前被创建过(所有创建过的单实例Bean都会被缓存起来)
  • 缓存中获取不到,开始Bean的创建对象流程
  • 标记当前bean已经被创建
  • 获取Bean的定义信息
  • 获取当前Bean依赖的其他Bean,如果有按照getBean()把依赖的Bean先创建出来
  • 启动单实例Bean的创建流程:

createBean(beanName, mbd, args)

resolveBeforeInstantiation(beanName, mbdToUse):让BeanPostProcessor先拦截返回代理对象,InstantiationAwareBeanPostProcessor提前执行,先触发postProcessBeforeInstantiation(),如果有返回值则触发postProcessAfterInitialization()

doCreateBean(beanName, mbdToUse, args):创建Bean

将创建的Bean添加到缓存中singletonObjects

doCreateBean(beanName, mbdToUse, args):

揭秘Spring容器创建与启动:从零到运行的全过程图片

  • 创建Bean实例:利用工厂方法或者对象的构造器创建出Bean实例
  • 调用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition(mbd, beanType, beanName):bean合并后的处理,Autowired注解正是通过此方法实现诸如类型的预解析,可查看AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
  • getEarlyBeanReference(beanName, mbd, bean):创建这个Bean的ObjectFactory的对象,并且把他加到第三级缓存中,主要用来解决循环依赖
  • populateBean(beanName, mbd, instanceWrapper):Bean属性赋值

拿到InstantiationAwareBeanPostProcessor后置处理器,执行postProcessAfterInstantiation()和postProcessPropertyValues()

applyPropertyValues(beanName, mbd, bw, pvs):应用Bean属性的值,为属性利用setter方法等进行赋值

  • initializeBean(beanName, exposedObject, mbd):Bean初始化
  • invokeAwareMethods(beanName, bean):执行xxxAware接口的方法

  • applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName):执行后置处理器初始化之前

  • invokeInitMethods(beanName, wrappedBean, mbd):执行初始化方法,是否是InitializingBean接口的实现;是否自定义初始化方法

  • applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName):执行后置处理器初始化之后

  • 从一级或者二级缓存中获取Bean的实例,不从三级缓存中取

  • 注册Bean的销毁方法

12.完成BeanFactory的初始化创建工作:

揭秘Spring容器创建与启动:从零到运行的全过程图片

finishRefresh()

  • initLifecycleProcessor():初始化和生命周期有关的后置处理器,默认从容器中找是否有lifecycleProcessor的组件,如果没有new DefaultLifecycleProcessor()加入到容器
  • getLifecycleProcessor().onRefresh():拿到前面定义的生命周期处理器(BeanFactory回调onRefresh()
  • publishEvent(new ContextRefreshedEvent(this)):发布容器刷新完成事件
  • liveBeansView.registerApplicationContext(this):向容器中注册spring.liveBeansView.mbeanDomain

原文地址:https://mp.weixin.qq.com/s/ZcGw7wIl9VEt-_zLlaBRSw

延伸 · 阅读

精彩推荐