Spring是如何设计IOC容器的?BeanFactory ApplicationContext

2024-06-18 17:52

本文主要是介绍Spring是如何设计IOC容器的?BeanFactory ApplicationContext,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

BeanFactory是Spring框架中最底层的接口,用于实例化、配置和管理bean。它使用控制反转(IOC)模式,将对象的创建、管理和装配的职责从应用程序代码中转移给Spring容器。这样,应用程序代码就无需关心对象如何创建和装配,只需从容器中获取所需的对象即可。关于BeanFactory和Bean的实例化,有几点需要明确:

  1. 延迟初始化:BeanFactory默认采用延迟初始化的策略。这意味着当你创建一个BeanFactory实例时,它并不会立即实例化容器中定义的所有Bean。相反,它会等待直到某个Bean第一次被请求时,才会实例化该Bean。这种策略可以提高应用程序的启动速度,因为不是所有的Bean在启动时就都需要被实例化。
  2. 依赖注入:当BeanFactory被要求实例化一个Bean时,它会查看该Bean的依赖关系,并根据配置自动装配这些依赖。这通常通过自动装配(如通过构造函数、setter方法或字段注入)或手动装配(在XML配置文件中或通过Java配置类指定)来完成。
  3. 作用域:Spring容器中的Bean有不同的作用域(如单例、原型、请求、会话等)。BeanFactory会根据Bean的作用域来决定如何实例化和管理Bean。例如,单例Bean在整个容器生命周期内只会被实例化一次,而原型Bean每次被请求时都会实例化。
  4. 生命周期管理:除了实例化和依赖注入外,BeanFactory还负责管理Bean的生命周期。BeanPostProcessor 与 BeanFactoryPostProcessor 。

Spring 设计了两个接口用以表示容器:BeanFactory && ApplicationContext。BeanFactory和ApplicationContext是Spring的两大核心接口,都可以当做Spring的容器。其中ApplicationContext是BeanFactory的子接口。

1、BeanFactory 就是个 HashMap,Key 是 beanName,Value 是 Bean 实例。Spring里面最底层的接口:读取bean配置文档,包含了各种Bean的定义,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。我们可以称之为 “低级容器”。
ApplicationContext 可以称之为 “高级容器”,是 Spring 应用上下文。他继承了多个接口,因此具备了更多的功能:

1、EnvironmentCapable:为applicationContext声明了获取激活profile、默认profile 方法的功能,也即Environment这个接口代表应用运行时的环境。
2、MessageSource:支持消息的参数化和国际化
3、ApplicationEventPublisher:事件发布
4、ResourcePatternResolver:统一的资源文件访问方式
5、ListableBeanFactory:继承了BeanFactory,实现了枚举方法列举出当前BeanFactory中所有的bean对象而不必根据name一个一个的获取。
6、HierarchicalBeanFactory:是一个具有层级关系的Bean 工厂,拥有属性parentBeanFactory:当获取 Bean对象时,如果当前BeanFactory中不存在对应的bean,则会访问其直接 parentBeanFactory 以尝试获取bean 对象。载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层。

2、BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。

ApplicationContext,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。ApplicationContext启动后预载入所有的单实例Bean,通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。

相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。

3、BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:在BeanFactory中,需要手动注册BeanPostProcessor和BeanFactoryPostProcessor。这意味着开发者需要显式地在代码中调用相关方法来完成注册过程。相比之下,ApplicationContext会自动注册BeanPostProcessor和BeanFactoryPostProcessor。这意味着开发者无需显式注册这些后处理器,Spring容器会在启动时自动完成这一过程。

在Spring框架中,BeanFactoryPostProcessor 是一个特殊的bean,允许你在Spring容器实例化bean之前修改或定制应用上下文中的bean定义。BeanFactoryPostProcessor 的主要应用场景包括添加或修改bean的属性、修改bean之间的依赖关系等。

在Spring容器的初始化过程中,特别是在refresh()方法中,会调用invokeBeanFactoryPostProcessors()方法来执行所有的BeanFactoryPostProcessor。下面是invokeBeanFactoryPostProcessors()方法的基本逻辑概述:

  1. 检测BeanFactoryPostProcessor bean:Spring首先会检查容器中已经注册的所有bean定义,找出所有实现了BeanFactoryPostProcessor接口的bean。
  2. 实例化BeanFactoryPostProcessor bean:对于检测到的每一个BeanFactoryPostProcessor bean,Spring会实例化它们。但是,因为BeanFactoryPostProcessor本身也是bean,所以它们的实例化也会受到Spring的生命周期管理。
  3. 排序:如果BeanFactoryPostProcessor实现了Ordered接口或标记了@Order注解,那么Spring会按照定义的顺序来调用它们。此外,如果BeanFactoryPostProcessor实现了PriorityOrdered接口,那么这些bean会具有更高的优先级,并在普通的Ordered bean之前被调用。
  4. 调用postProcessBeanFactory方法:对于每一个BeanFactoryPostProcessor实例,Spring会调用其postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法。这个方法允许你修改或定制传入的ConfigurableListableBeanFactory,这个对象代表了Spring IoC容器当前的内部状态。
  5. 继续容器初始化:在所有BeanFactoryPostProcessor被调用并处理完毕后,Spring容器会继续其初始化过程,包括实例化、依赖注入、调用初始化方法等步骤。

通过BeanFactoryPostProcessor,你可以获得对Spring IoC容器内部状态的控制,并在bean实例化之前修改bean定义。这种能力使得BeanFactoryPostProcessor在Spring的扩展性和灵活性方面发挥了重要作用。

在Spring框架中,BeanPostProcessor接口允许开发者在Spring IoC容器实例化bean后、初始化方法(如果有的话)调用前和调用后插入自定义的逻辑。这是Spring AOP(面向切面编程)功能的一部分,虽然BeanPostProcessor本身并不直接实现AOP,但它为AOP提供了基础。

以下是BeanPostProcessor在Spring中使用的步骤:

  1. 定义BeanPostProcessor:你需要实现BeanPostProcessor接口,并重写postProcessBeforeInitialization和postProcessAfterInitialization方法。这两个方法分别在bean的初始化方法(如@PostConstruct注解的方法或实现了InitializingBean接口中的afterPropertiesSet方法)调用之前和之后被调用。
public class CustomBeanPostProcessor implements BeanPostProcessor {  @Override  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  // 在bean的初始化方法之前执行的逻辑  System.out.println("Before initialization: " + beanName);  return bean;  }  @Override  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  // 在bean的初始化方法之后执行的逻辑  System.out.println("After initialization: " + beanName);  return bean;  }  
}
  1. 注册BeanPostProcessor:将你的BeanPostProcessor实现注册到Spring容器中。这可以通过XML配置或Java配置完成。
<bean class="com.example.CustomBeanPostProcessor" />
@Configuration  
public class AppConfig {  @Bean  public CustomBeanPostProcessor customBeanPostProcessor() {  return new CustomBeanPostProcessor();  }  // ... 其他bean的定义 ...  
}
  1. 使用:一旦BeanPostProcessor被注册到容器中,Spring就会在创建并初始化每个bean时自动调用它。你不需要在代码中显式地调用BeanPostProcessor。需要注意的是,BeanPostProcessor自身也会被当作一个bean来处理,这意味着BeanPostProcessor也会受到BeanPostProcessor链的影响。因此,在定义多个BeanPostProcessor时,需要注意它们之间的依赖关系和初始化顺序。

通过BeanPostProcessor,你可以对Spring容器中的bean进行拦截,并在bean的生命周期中的关键点上添加自定义逻辑。这对于诸如日志记录、安全检查、性能监控等横切关注点(cross-cutting concerns)非常有用。

在这里插入图片描述

这篇关于Spring是如何设计IOC容器的?BeanFactory ApplicationContext的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2

Spring Cloud LoadBalancer 负载均衡详解

《SpringCloudLoadBalancer负载均衡详解》本文介绍了如何在SpringCloud中使用SpringCloudLoadBalancer实现客户端负载均衡,并详细讲解了轮询策略和... 目录1. 在 idea 上运行多个服务2. 问题引入3. 负载均衡4. Spring Cloud Load

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

在 Spring Boot 中使用 @Autowired和 @Bean注解的示例详解

《在SpringBoot中使用@Autowired和@Bean注解的示例详解》本文通过一个示例演示了如何在SpringBoot中使用@Autowired和@Bean注解进行依赖注入和Bean... 目录在 Spring Boot 中使用 @Autowired 和 @Bean 注解示例背景1. 定义 Stud

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2