1.【Spring源码】- 02 Spring IoC容器启动之refresh方法
2.Spring IoC源码深度剖析
3.SpringIoc 容器之 Aware | 京东云技术团队
【Spring源码】- 02 Spring IoC容器启动之refresh方法
在注册阶段,码解AnnotationConfigApplicationContext构造方法中的码解第一个方法被分析过。接下来,码解我们关注第二个方法:register(componentClasses)。码解在使用XML配置方式时,码解通过new ClassPathXmlApplicationContext("classpath:spring.xml")来创建实例,码解检查版本源码其中需要指定xml配置文件路径。码解使用注解方式时,码解也需要为ApplicationContext提供起始配置源头,码解这里使用配置类代替xml配置文件,码解按照配置类中的码解注解(如@ComponentScan、@Import、码解@Bean)解析并注入Bean到IoC容器。码解
通过配置类,码解Spring解析注解实现Bean的码解ubuntu node源码安装路径注入。使用@Configuration注解定义的配置类相当于xml配置文件,但目前Spring推荐使用注解方式,xml配置的使用概率正在降低。
register(componentClasses)方法的核心逻辑在AnnotatedBeanDefinitionReader#doRegisterBean中,将传入的配置类解析为BeanDefinition并注册到IoC容器。ConfigurationClassPostProcessor这个BeanFactory后置处理器在IoC初始化时,获取配置类的BeanDefinition集合,开始解析。
真正启动IoC容器的流程在refresh()方法中,这是了解IoC容器启动流程的关键步骤。refresh方法在AbstractApplicationContext中定义,采用模板模式,提供IoC初始化流程的基本实现,子类可以扩展。魔兽世界CD宏源码
下面分析refresh()方法的每个步骤,以了解IoC容器的启动流程。
prepareRefresh方法主要在refresh执行前进行准备工作,如设置Context的启动时间、状态,以及扩展系统属性相关。
initPropertySources()方法主要用于扩展配置来源,如网络、物理文件、数据库等加载配置信息。StandardEnvironment默认只提供加载系统变量和应用变量的功能,用于子类扩展。
❝initPropertySources方法常见扩展场景包括:❞
getEnvironment().validateRequiredProperties()确保设置的必要属性在环境中存在,否则抛出异常终止应用。伊计任务平台源码
BeanFactory是Spring的基本IoC容器,ApplicationContext包装了BeanFactory,提供更智能、更便捷的功能。ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();获取的BeanFactory是IoC容器初始化工作的基础。
上面获取的BeanFactory还不能直接使用,需要填充必要的配置信息。至此,IoC容器的启动流程基本完成。
这里对IoC启动流程有个大致、直观的印象。主要步骤包括:准备阶段、配置来源扩展、初始化BeanFactory、仿短信app界面源码填充配置、解析配置类、注册Bean、实例化BeanPostProcessor、初始化国际化和事件机制、以及创建内嵌Servlet容器(在SpringBoot中实现)。这些步骤确保了IoC容器顺利启动并管理Bean。
Spring IoC源码深度剖析
Spring IoC容器初始化深度剖析
Spring IoC容器是Spring的核心组件,主要负责对象管理和依赖关系管理。容器体系丰富多样,如BeanFactory作为顶层容器,它定义了所有IoC容器的基本原则,而ApplicationContext及其子类如ClassPathXmlApplicationContext和AnnotationConfigApplicationContext则提供了额外功能。Spring IoC容器的初始化流程关键在AbstractApplicationContext的refresh方法中。 1.1 初始化关键点 通过创建特定类LagouBean并设置断点,我们发现Bean的创建在未设置延迟加载时,发生在容器初始化过程中。构造函数调用、InitializingBean的afterPropertiesSet方法以及BeanFactoryPostProcessor和BeanPostProcessor的初始化和调用,都在refresh方法的不同步骤中发生。 1.2 主体流程概览 Spring IoC容器初始化的主体流程主要集中在AbstractApplicationContext的refresh方法,涉及Bean对象创建、构造函数调用、初始化方法执行和处理器调用等步骤。 1.3 深度剖析 分析发现,延迟加载机制使得懒加载的bean在第一次调用getBean时才进行初始化。而对于非懒加载bean,它们在容器初始化阶段已经完成并缓存。Spring处理循环依赖的方法依赖于构造器调用的顺序规则,不支持原型bean的循环依赖,而对单例bean则通过setXxx或@Autowired方法提前暴露对象来避免循环依赖。SpringIoc 容器之 Aware | 京东云技术团队
Aware 是 Spring 提供的一个标记超接口,它允许 bean 通过回调式方法接受 Spring 容器的通知,进而获取到容器中特定对象的实例。方法的具体实现由各个子接口决定,通常包含一个接收单个参数并返回 void 的方法。
Spring 中包含了 9 个内置的 Aware 实现,这些实现大致分为两类。前三个实现通过直接调用完成,而后六个则通过 ApplicationContextAwareProcessor 后置处理器间接回调。
实现 BeanNameAware 接口的 bean 需要实现 setBeanName() 方法。此接口的主要作用在于让实现该接口的 bean 知道自己在 Spring 容器中的名称。官方建议实际开发中不建议使用此接口,因为 bean 名称在 Spring 容器中可能仅作为唯一标识,与 bean 的联系并不紧密。
BeanClassLoaderAware 接口在 bean 属性填充后初始化前提供类加载器的回调,用于让受管理的 bean 了解其是由哪个类加载器负责装载的。
BeanFactoryAware 接口在 bean 属性填充后初始化前提供 bean 工厂的回调,实现该接口的 bean 可以直接访问 Spring 容器,根据传入参数动态获取被 Spring 工厂加载的 bean。
EnvironmentAware 接口让所有注册到 Spring 容器内的 bean,在启动时能够获取 application.properties 配置文件的属性值,避免将魔法值写入代码中。
EmbeddedValueResolverAware 接口用于基于 Spring 解析 properties 文件属性值,适用于抽象类中基于 Spring 解析 @Value 的方式。
ResourceLoaderAware 接口希望拥有 ResourceLoader 引用的对象,允许实现该接口的 bean 在被 Spring 管理时,通过 application context 载入资源,但通常建议使用特定的满足所有需求的 ResourceLoader 实现。
ApplicationEventPublisherAware 接口提供了一个用于为 Service 注入 ApplicationEventPublisher 事件发布器的接口,使 Service 可以发布事件。
MessageSourceAware 接口让 bean 获得 message source,用于在国际化场景中获取文本信息。
ApplicationContextAware 接口允许 bean 方便地获取 Spring 容器ApplicationContext,从而获取容器内的 Bean。Spring 在创建实现类时自动执行此接口的方法,将 ApplicationContext 注入。
Spring 中的 Aware 接口在 AbstractAutowireCapableBeanFactory.initializeBean() 方法中,通过调用 invokeAwareMethods() 和 applyBeanPostProcessorsBeforeInitialization() 方法触发 Aware 方法的调用。
invokeAwareMethods() 方法直接回调,而 applyBeanPostProcessorsBeforeInitialization() 方法通过 ApplicationContextAwareProcessor.postProcessBeforeInitialization() 间接调用,并在方法 invokeAwareInterfaces() 中进行回调。
总结而言,Spring 使用两种方式调用 Aware 接口,旨在在 Spring 容器生命周期中提供灵活的回调机制,允许 bean 在初始化前获取不同上下文信息。通过理解这 9 种内置实现,开发者可以更好地利用 Spring 提供的灵活性和功能。