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

相关文章

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 声明式事物

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

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智听未来一站式有声阅读平台听书系统小程序源码

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