皮皮网
皮皮网

【derby 源码分析】【一千秒赞源码】【LEAN源码编译教程】spring context源码

来源:源码变反码 发表时间:2024-11-29 18:32:14

1.SpringBoot源码之容器刷新 refreshContext 方法详解
2.Spring系列SpringContext.getBean()方法调用导致NPE?
3.SpringBoot源码 | refreshContext方法解析
4.Spring Boot源码解析(四)ApplicationContext准备阶段
5.Spring源码- 02 Spring IoC容器启动之refresh方法
6.SpringContextUtil工具类实现

spring context源码

SpringBoot源码之容器刷新 refreshContext 方法详解

       深入探索 SpringBoot 容器刷新机制,重点解析 refreshContext 方法,引领你步入 SpringBoot 源码的神秘殿堂。

       刷新容器,首先进入 prepareRefresh 方法,为后续流程铺垫。derby 源码分析

       随后,obtainFreshBeanFactory 方法展开,围绕 DefaultListableBeanFactory 类,确保 Bean 加载与注册的顺利进行。

       准备 BeanFactory,通过 prepareBeanFactory 方法,为所有 Bean 的加载与注册工作做好铺垫。

       postProcessBeanFactory 方法加入后置处理器,确保 BeanFactory 的最终配置与校验。

       invokeBeanFactoryPostProcessors 方法启动,对所有已定义的扩展点进行加载,包括 BeanFactoryPostProcessorPoint 和 BeanDefinitionRegistryPostProcessorPoint,丰富 Spring 的功能。

       注册监听器与系统事件,onRefresh 方法负责,通过 ApplicationListener 对象,执行事件的广播与响应。

       finishBeanFactoryInitialization 方法,聚焦于 singleton beans 的初始化,确保单例 Bean 的正确创建与配置。

       preInstantiateSingletons 方法,对 BeanFactory 中的实例进行预实例化处理,确保懒加载 Bean 的正常启动。

       深入getBean方法,解析 Bean 的一千秒赞源码创建与属性注入过程,从类型与名称注入,到回调处理,每一个细节都不可或缺。

       属性注入完成,意味着 Bean 的初始化工作接近尾声,通过回调机制,观察扩展点的丰富性与灵活性。

       总结,SpringBoot 的容器刷新机制,不仅高效管理 Bean 的生命周期,还通过扩展点的灵活配置,为开发者提供了强大的自定义能力。

       本文仅作为 SpringBoot 容器刷新方法的初步解析,期待后续文章深入探讨扩展点的实现与应用,如有任何疑问或错误,欢迎指正。

       参考来源:javadoop.com/post/spring...

Spring系列SpringContext.getBean()方法调用导致NPE?

       在实际的业务开发中,为了方便获取Spring容器中的Bean对象,一个常见的做法是创建一个SpringUtil类,内部持有SpringContext上下文,然后提供一个静态方式获取bean对象。然而,这种使用姿势可能不慎导致NPE(空指针异常)。我们接下来将探讨这一场景及其复现过程。

       为了搭建基础环境,我们可以创建一个基于SpringBoot 2.2.1.RELEASE的项目,使用maven 3.5.3和IDEA进行开发。然后,我们构建一个简单的SpringUtil工具类,通过SpringContextAware持有上下文。LEAN源码编译教程

       接着,我们创建一个简单的bean对象和另一个依赖该对象的bean。重点关注依赖bean内部的枚举类,它通过SpringUtil获取BasicDemo对象,并调用其私有方法show()及包内方法test()。这种用法是否存在问题呢?

       我们编写一个接口测试,尝试访问上述实现。出乎意料的是,虽然存在潜在的NPE风险,但在正常情况下,服务端返回了一个合理的响应。随后,我们添加一个切面,使通过SpringUtil.getBean获取到的对象成为代理类,再进行请求测试。此时,访问私有方法show()时抛出异常,从堆栈信息看到异常类型为NPE。原来,在访问代理类的私有方法时,内部注入的bean对象为null,导致了NPE异常。

       若将私有方法show()改为调用一个bean对象的公共方法,再次测试,发现没有问题。这一现象显得颇为神奇。那么,是什么原因导致了这种差异呢?

       通过SpringContext获取到的bean对象时,直接访问其私有方法可能导致NPE。这个问题通常出现在类内部方法调用希望被切面拦截的python的方法源码方法,或者在反射执行某些逻辑时访问私有方法的场景。

       总结:当我们通过SpringContext获取到的bean对象时,不要直接访问它的私有方法,以避免潜在的NPE问题。这一现象揭示了在访问私有方法时需注意的常见场景及其潜在风险。后续的分析将深入探讨具体原因。

SpringBoot源码 | refreshContext方法解析

       本文主要解析SpringBoot启动流程中的`refreshContext`方法。在SpringBoot启动过程中,主要涉及两个阶段:初始化`SpringApplication`对象和`SpringApplication.run`方法执行的内容。`refreshContext`方法的执行,标志着启动流程的深入。

       `refreshContext`方法的主要功能是刷新容器,其源码揭示了这一过程的关键步骤。首先,方法通过调用`refresh`来实现底层`ApplicationContext`的刷新。`ApplicationContext`接口的抽象实现类`AbstractApplicationContext`,通过模板方法设计模式,要求具体子类实现抽象方法,以适应不同的配置存储需求。

       `refresh`方法执行了一系列操作,包括准备刷新上下文、调用上下文注册为bean的工厂处理器、初始化上下文的消息源、初始化特定上下文子类中的其他特殊bean、检查监听器bean并注册,以及发布相应的事件并销毁已经创建的单例及重置active标志。

       在`refresh`方法内部,`prepareRefresh`方法负责准备上下文以进行刷新,包括设置启动日期和活动标志,以及执行属性源的企查猫源码初始化。`obtainFreshBeanFactory`方法获取新的bean工厂,通过`refreshBeanFactory`方法进行配置,以及`getBeanFactory`方法返回当前上下文的内部bean工厂。

       `prepareBeanFactory`方法配置工厂标准的上下文特征,如上下文类加载器、后置处理器等。`postProcessBeanFactory`方法进一步处理bean工厂,根据WebApplicationType选择特定的操作,如添加后置处理器以及注册特定的web作用域。

       `invokeBeanFactoryPostProcessors`方法调用bean工厂的后置处理器,`registerBeanPostProcessors`方法实例化并注册所有后置处理器bean。`initMessageSource`方法初始化应用上下文消息源,而`initApplicationEventMulticaster`方法则为上下文初始化事件多播。

       `onRefresh`方法执行刷新操作,`createWebServer`方法创建web服务,`registerListeners`方法检查并注册监听器。`finishBeanFactoryInitialization`方法实例化所有剩余的单例bean,而`finishRefresh`方法发布事件,重置Spring核心中的公共内省缓存,标志着容器刷新的结束。

       `resetCommonCaches`方法重置Spring核心中的公共内省缓存,`contextRefresh.end`方法容器刷新结束,最终执行日志打印,完成启动流程。

       总的来说,`refreshContext`方法的执行流程清晰,通过丰富的源码注释,便于学习者深入理解SpringBoot启动机制。本文仅提供方法解析的概览,更多细节请参考原始源码。

Spring Boot源码解析(四)ApplicationContext准备阶段

       深入解析Spring Boot中ApplicationContext的准备阶段,本文将带你从环境设置、后处理到初始化器的执行,直至广播事件和注册应用参数等关键步骤的全面解读。

       环境的设置是准备阶段的起点,主要涉及三个步骤。首先,通过AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner,将包含实际参数的Environment重新配置到这些实例中,以确保ApplicationContext能够准确理解和处理后续的配置信息。

       紧接着,对ApplicationContext进行后处理。这包括注册beanNameGenerator、设置resourceLoader和conversionService。对于一般配置的Spring Boot应用,这些部分往往为空,因此主要执行的是设置conversionService,确保数据转换的顺利进行。

       处理Initializer阶段,Spring Boot通过遍历META-INF/spring.factories中的initializer加载配置,执行8个预设的Initializer方法,它们负责执行特定的功能,例如增强或定制ApplicationContext行为,尽管具体实现细节未详细展开。

       广播ApplicationContextInitialized和BootstrapContextClosed事件,以及注册applicationArguments和printedBanner,是准备阶段的后续操作,确保ApplicationContext能够接收外部参数并展示启动信息,同时为ApplicationContext的后续操作做准备。

       在设置不支持循环引用和覆盖后,调整lazy initialization为默认不允许。Spring Boot通过配置确保依赖注入过程的高效性和稳定性,同时提供了开启懒加载的选项,允许在实际使用时加载bean,提高应用启动性能。

       最后,处理重排属性的post processor,确保ConfigurationClassPostProcessor加载的property在正确的位置被处理,维护配置加载的逻辑顺序和依赖关系。

       资源的加载是准备阶段的最后一步,将PrimarySource与所有其他源整合到allSources中,并返回一个不可修改的集合。这个过程确保了资源的高效访问和管理,为ApplicationContext的后续操作提供基础。

       在完成启动类的加载后,Spring Boot通过构建BeanDefinitionLoader并配置相应的组件,将主类Application加载到Context中。这一过程是动态且高效的,确保了应用的快速启动和资源的有效管理。

       至此,Spring Boot中ApplicationContext的准备阶段全面解析完成,从环境设置到启动类加载,每一个步骤都为ApplicationContext的高效运行打下了坚实的基础。接下来,我们将探讨ApplicationContext的刷新过程,敬请关注。

Spring源码- Spring IoC容器启动之refresh方法

       在注册阶段,AnnotationConfigApplicationContext构造方法中的第一个方法被分析过。接下来,我们关注第二个方法:register(componentClasses)。在使用XML配置方式时,通过new ClassPathXmlApplicationContext("classpath:spring.xml")来创建实例,其中需要指定xml配置文件路径。使用注解方式时,也需要为ApplicationContext提供起始配置源头,这里使用配置类代替xml配置文件,按照配置类中的注解(如@ComponentScan、@Import、@Bean)解析并注入Bean到IoC容器。

       通过配置类,Spring解析注解实现Bean的注入。使用@Configuration注解定义的配置类相当于xml配置文件,但目前Spring推荐使用注解方式,xml配置的使用概率正在降低。

       register(componentClasses)方法的核心逻辑在AnnotatedBeanDefinitionReader#doRegisterBean中,将传入的配置类解析为BeanDefinition并注册到IoC容器。ConfigurationClassPostProcessor这个BeanFactory后置处理器在IoC初始化时,获取配置类的BeanDefinition集合,开始解析。

       真正启动IoC容器的流程在refresh()方法中,这是了解IoC容器启动流程的关键步骤。refresh方法在AbstractApplicationContext中定义,采用模板模式,提供IoC初始化流程的基本实现,子类可以扩展。

       下面分析refresh()方法的每个步骤,以了解IoC容器的启动流程。

       prepareRefresh方法主要在refresh执行前进行准备工作,如设置Context的启动时间、状态,以及扩展系统属性相关。

       initPropertySources()方法主要用于扩展配置来源,如网络、物理文件、数据库等加载配置信息。StandardEnvironment默认只提供加载系统变量和应用变量的功能,用于子类扩展。

       ❝initPropertySources方法常见扩展场景包括:❞

       getEnvironment().validateRequiredProperties()确保设置的必要属性在环境中存在,否则抛出异常终止应用。

       BeanFactory是Spring的基本IoC容器,ApplicationContext包装了BeanFactory,提供更智能、更便捷的功能。ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();获取的BeanFactory是IoC容器初始化工作的基础。

       上面获取的BeanFactory还不能直接使用,需要填充必要的配置信息。至此,IoC容器的启动流程基本完成。

       这里对IoC启动流程有个大致、直观的印象。主要步骤包括:准备阶段、配置来源扩展、初始化BeanFactory、填充配置、解析配置类、注册Bean、实例化BeanPostProcessor、初始化国际化和事件机制、以及创建内嵌Servlet容器(在SpringBoot中实现)。这些步骤确保了IoC容器顺利启动并管理Bean。

SpringContextUtil工具类实现

       Spring的SpringContextUtil工具类主要用于简化ApplicationContext的管理。首先,你需要创建一个实现了ApplicationContextAware接口的工具类,这个接口会在setApplicationContext方法中自动注入ApplicationContext,从而完成初始化过程。

       然而,为了确保ApplicationContext在使用时不会抛出NullPointException,你需要在Spring配置文件(applicationContext.xml)中进行适当的设置。通常,配置文件中存在"default-default-lazy-init"属性,默认值为true,表示延迟加载。这可能导致在Spring启动时,所有对象实例图会一次性加载,包括ACTION、service、dao以及数据库连接等,导致启动速度变慢。因此,在开发环境中,我们通常将其改为false,即立即加载。

       在代码中使用SpringContextUtil时,记得添加lazy-init="false"属性到需要注入ApplicationContext的配置中,这样可以确保ApplicationContext在需要时立即加载,避免NullPointException的发生。

相关栏目:休闲