Spring容器初始化全过程

2024-06-11 05:48

本文主要是介绍Spring容器初始化全过程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

spring容器主要有三种初始化方式,xml;注解;JavaConfig+注解形式,这里以目前最前卫的JavaConfig初始化方式来解读整个容器的初始化。(毕竟spring官方都强烈建议这种初始化方式,但可悲的是,国内的大部分中小企业还是使用传统的xml...)

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

这是spring的入口类,spring容器的所有初始化操作都由此开始。

一、首先调用父类GenericApplicationContext的无参构造方法,实例化DefaultListableBeanFactory,这是spring的核心bean工厂,所有BeanDefinition会存放在这里,所有后置处理器也会在这里,在实现BeanFactory接口的同时也实现了BeanDefinitionRegistry接口,因此它就承担了Bean的注册管理工作。BeanDefinitionRegistry的相关接口负责注册工作,BeanFactory的相关接口负责bean的管理工作。

二、调用自身的无参构造方法,主要实例化了两个功能性对象AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner,其中最主要的是往beanDefinitionMap中put了spring自己的6个BeanDefinition,各自有各自的功能。注意这里并不是真正的Bean,BeanDefinition和后面Bean的生成有很重要的关系

  • ConfigurationClassPostProcessor

spring中最最重要的一个类,实现了BeanDefinitionRegistryPostProcessor接口,能扫描到所有的bean(通过@ComponentScan;@Bean;@Import;等注入的bean),并注册为bd

  • AutowiredAnnotationBeanPostProcessor

spring中为bean进行属性注入的后置处理器,包括解决循环依赖的问题

  • RequiredAnnotationBeanPostProcessor

处理@Required注解相关的后置处理器

  • CommonAnnotationBeanPostProcessor

通用注解的后置处理器,@Resource属性的注入也是在这当中

  • EventListenerMethodProcessor

    不清楚

  • DefaultEventListenerFactory

不清楚

三、register(annotatedClasses) 注册初始传入的配置类为bd。

四、refresh() spring容器初始化最核心的部分,这里处理了其90%的初始化工作。

  • prepareRefresh()

准备工作包括设置启动时间,是否激活标识位,初始化属性源(property source)配置

  • prepareBeanFactory(beanFactory)

准备bean工厂,这里就包括了ApplicationContextAwareProcessor(处理各种实现了*Aware 接口的bean)这个BeanPostProcessor的add

  • postProcessBeanFactory(beanFactory)

属于spring的预留接口,在后面的版本中扩展

  • invokeBeanFactoryPostProcessors(beanFactory)

spring核心方法,处理执行自定义的和spring内部定义的 BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessors,spring中那个最最重要的一个 类ConfigurationClassPostProcessor就是在这处理的,这里针对不同的来源,遵循以下执行顺序

1.自定义(手动add进来的)BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法

2.spring容器中实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry                方法

3.spring容器中实现了Ordered接口的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法

4.spring容器中其他(实现了PriorityOrdered和Ordered之外的)BeanDefinitionRegistryPostProcessor的                                          postProcessBeanDefinitionRegistry方法

5.所有(包括自定义的和由spring管理的)BeanDefinitionRegistryPostProcessor的父类BeanFactoryPostProcessor的                    postProcessBeanFactory方法

6.所有自定义的BeanFactoryPostProcessor的postProcessBeanFactory方法

7.所有spring管理的BeanFactoryPostProcessor(实现了PriorityOrdered接口)的postProcessBeanFactory方法

8.所有spring管理的BeanFactoryPostProcessor(实现了Ordered接口)的postProcessBeanFactory方法

9.所有spring管理的BeanFactoryPostProcessor(实现了PriorityOrdered和Ordered之外的)的postProcessBeanFactory                 方法

  • registerBeanPostProcessors(beanFactory)

添加BeanPostProcessor到DefaultListableBeanFactory中的名为beanPostProcessors的List中,所以spring的所有后置处理器都是放在一个List中的

  • initMessageSource()

初始化国际化信息

  • initApplicationEventMulticaster()

初始化应用事件广播器

  • onRefresh()

属于spring的预留接口,在后面的版本中扩展

  • registerListeners()

spring event 注册事件监听器

  • finishBeanFactoryInitialization(beanFactory)

spring核心方法 实例化bean,bean的整个生命周期也从这里开始

1) 实例化之前首先去单例池中获取:getBean ---doGetBean---getSingleton,如果获取不到从singletonObjects中获取(解决bean的循环依赖问题)

2) 如果上一步没有获取到bean,就会进入bean的创建流程,执行第一次后置处理器 InstantiationAwareBeanPostProcessor#applyBeanPostProcessorsBeforeInstantiation

方法如果有返回值,将代替原本该生成的目标对象的实例,后续将只会调用所有BeanPostProcessor#postProcessAfterInitialization方法,下面的初始化操作将不再执行,这个后置处理器的经典应用场景是spring aop的代理增强剔除不必要增强的类

3) 执行第二次后置处理器SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors推断构造方法,如果有特殊的构造方法(@Autowired/@Value修饰)或者是标识首选的构造方法,则使用特殊的构造方法进行初始化,如果只有一个默认的构造方法,则返回null,就会再接下来使用默认的无参构造方法进行初始化,其实现类是AutowiredAnnotationBeanPostProcessor

4) 经过上一步之后,目标对象已经被new出来了,只是这个时侯还是对象,并不是一个bean,执行第三次后置处理器,MergedBeanDefinitionPostProcessor # postProcessMergedBeanDefinition 缓存bean实例化时须要通过注解注入的对象信息

5) addSingletonFactory,执行第四次后置处理器,SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference(其实不是第四次,因为是通过lambd表达式注入的,后续要用的时候才会用),将对象提前暴露出来,主要是为了解决spring循环依赖的问题

6) populateBean,对bean的属性赋值,这里会执行第五次后置处理器,InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation,确定是否须要注入属性,实现这个接口,返回的bean就不做后续的初始化操作了

7) 执行第六次后置处理器,InstantiationAwareBeanPostProcessor#postProcessPropertyValues,这里将完成属性注入,其中处理@AutoWired注解也是在这里来处理的

8) initializeBean,执行到这一步,对象已经完成了属性装配,可以称作为一个bean了,这里会相继执行第七次后置处理器BeanPostProcessor # postProcessBeforeInitialization;执行InitializingBean的实现;执行第八次后置处理器BeanPostProcessor # postProcessAfterInitialization,完成对bean的最后实例化阶段,最终实例化完成的单例bean将放在DefaultSingletonBeanRegistry中的一个Map中(singletonObjects)

  • finishRefresh()

至此结束整个容器的初始化过程

 

这篇关于Spring容器初始化全过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1050350

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟 开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚 第一站:海量资源,应有尽有 走进“智听

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定