0%

Spring 容器深度解析:从 BeanFactory 到 ApplicationContext 的体系与实践

Spring 容器是 IOC(控制反转)思想的具体实现,核心职责是管理 Bean 的生命周期(创建、装配、销毁)与依赖关系,是 Spring 框架的 “心脏”。Spring 提供了两类核心容器:BeanFactory(基础容器)和 ApplicationContext(高级容器),二者在功能、初始化策略和适用场景上存在显著差异。从 “容器体系→核心实现→关键区别→Bean 定义元数据” 四个维度,彻底拆解 Spring 容器的工作机制。

Spring 容器体系总览

Spring 容器基于 “分层设计”,从基础到高级形成完整体系,核心接口与实现类的关系如下:

spring容器

核心设计思路:BeanFactory 定义基础规范,ApplicationContext 在其之上扩展高级功能,满足不同场景需求(轻量级 vs 企业级)。

基础容器:BeanFactory 详解

BeanFactory 是 Spring 容器的顶层接口,定义了 IOC 容器的最小功能集 ——“获取 Bean、判断 Bean 状态”,是 Spring 框架内部使用的基础容器(面向框架基础设施)。

1. BeanFactory 核心接口与方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public interface BeanFactory {
// 关键常量:区分 FactoryBean 本身与它生成的对象(前缀 "&")
String FACTORY_BEAN_PREFIX = "&";

// 1. 获取 Bean(核心方法,支持按名称、类型、带参数构造)
Object getBean(String name) throws BeansException; // 按名称获取(返回 Object,需强转)
<T> T getBean(String name, Class<T> requiredType) throws BeansException; // 按名称+类型(无需强转)
Object getBean(String name, Object... args) throws BeansException; // 带构造参数(创建原型 Bean 时用)
<T> T getBean(Class<T> requiredType) throws BeansException; // 按类型获取(推荐,更类型安全)
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException; // 按类型+构造参数

// 2. 判断 Bean 状态
boolean containsBean(String name); // 容器中是否存在该名称的 Bean
boolean isSingleton(String name) throws NoSuchBeanDefinitionException; // 是否为单例(默认)
boolean isPrototype(String name) throws NoSuchBeanDefinitionException; // 是否为原型(每次 getBean 新建)
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException; // Bean 类型是否匹配
Class<?> getType(String name) throws NoSuchBeanDefinitionException; // 获取 Bean 的类型
String[] getAliases(String name); // 获取 Bean 的别名(一个 Bean 可多个别名)
}
关键方法解析:
  • FACTORY_BEAN_PREFIX = "&":特殊前缀,用于获取FactoryBean本身(而非其生成的对象)。例如:
    • getBean("userFactory"):获取 userFactory 这个 FactoryBean 生成的 User 对象;
    • getBean("&userFactory"):获取 userFactory 这个 FactoryBean 实例本身。
  • getBean 重载:支持多种获取方式,按类型获取(getBean(Class<T>))是最常用的,避免强转,更安全。
  • 单例 / 原型判断isSingletonisPrototype 对应 Bean 的 scope 配置(默认单例)。

2. BeanFactory 的核心子类

BeanFactory 接口本身不实现具体逻辑,其功能通过三个核心子类扩展:

阅读全文 »

MySQL 表结构修改全解析:从编码到列定义

在数据库维护过程中,修改表结构是常见操作,包括调整编码、修改列名、增减字段等。MySQL 提供了丰富的 ALTER TABLE 语句支持这些操作,本文详细讲解各类修改场景的语法和注意事项。

修改编码格式(数据库 / 表 / 字段)

编码格式不匹配可能导致中文乱码或表情存储失败,需根据需求调整为 utf8utf8mb4(支持表情)。

1. 修改数据库编码

1
2
-- 语法:ALTER DATABASE 数据库名 CHARACTER SET 编码 [COLLATE 校对规则];
ALTER DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  • 影响:新表默认使用该编码,已有表不受影响。

2. 修改表编码

1
2
-- 语法:ALTER TABLE 表名 CHARACTER SET 编码 [COLLATE 校对规则];
ALTER TABLE users CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  • 影响:表的默认编码更新,新添加的字段会继承该编码,已有字段需单独修改。

3. 修改字段编码

1
2
-- 语法:ALTER TABLE 表名 MODIFY 字段名 类型 CHARACTER SET 编码 [COLLATE 校对规则];
ALTER TABLE users MODIFY nickname VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
阅读全文 »

XML 命名空间:解决命名冲突的核心机制

在复杂的 XML 文档中,尤其是需要整合多个来源的 XML 片段(如不同标准、不同系统的配置)时,元素或属性重名的情况极为常见。例如,<table>元素在 HTML 中表示表格,在数据库 XML 中可能表示数据表,这种命名冲突会导致解析歧义。XML 命名空间(XML Namespace) 正是为解决此类问题而生,它通过为元素和属性分配唯一的 “命名空间标识”,明确区分相同名称的不同含义。

XML 命名空间的核心概念

  • 命名空间:本质是一个唯一的标识符(通常是 URI,如http://www.springframework.org/schema/beans),用于标识一组 XML 元素和属性的 “归属”。
  • 前缀(Prefix):简化命名空间使用的短别名(如contextmvc),通过前缀与命名空间 URI 绑定,避免在每个元素中重复书写长 URI。
  • 默认命名空间:未指定前缀的元素默认归属的命名空间,简化文档书写。

命名空间的声明方式

XML 命名空间通过xmlns属性声明,有两种核心形式:带前缀的命名空间默认命名空间

带前缀的命名空间(显式声明)

通过xmlns:prefix="URI"的形式声明,其中:

阅读全文 »

Spring MVC Web 上下文初始化机制详解:从 web.xml 到注解配置

Web 上下文(WebApplicationContext)是 Spring MVC 在 Web 环境中的核心容器,负责管理 Bean 的生命周期并与 Servlet 容器集成。其初始化过程与 ServletContext 紧密绑定,生命周期完全一致。从 “传统 web.xml 配置→ContextLoaderListener 工作原理→Servlet 3.0 注解配置” 三个维度,彻底解析 Spring MVC Web 上下文的初始化机制。

Web 上下文与 ServletContext 的关系

在 Web 应用中,ServletContext 是 Servlet 容器(如 Tomcat)提供的全局上下文对象,代表整个 Web 应用,生命周期从应用启动到停止。而 Spring 的 WebApplicationContext 是 Spring 在 Web 环境中的 IOC 容器,依赖 ServletContext 存在,并通过 ServletContext 存储和获取,两者生命周期完全同步。

  • 存储位置WebApplicationContext 初始化后,会以固定键值(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,即 org.springframework.web.context.WebApplicationContext.ROOT)存入 ServletContext 的属性中,方便后续获取。
  • 核心作用WebApplicationContext 管理 Web 相关的 Bean(如 Controller、Service、Repository 等),并整合 Spring 与 Servlet 容器的交互(如请求处理、会话管理等)。

传统配置:基于 web.xml 与 ContextLoaderListener

在 Servlet 3.0 之前,Web 上下文的初始化依赖 web.xml 配置,核心是通过 ContextLoaderListener 触发初始化流程。

web上下文初始化流程

1. web.xml 核心配置

1
2
3
4
5
6
7
8
9
10
11
<!-- 1. 配置 ContextLoaderListener:触发 Web 上下文初始化 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- 2. 配置上下文配置文件路径(可选,默认有默认值) -->
<context-param>
<param-name>contextConfigLocation</param-name>
<!-- 多个配置文件用逗号分隔,支持 classpath: 或 /WEB-INF/ 前缀 -->
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
  • ContextLoaderListener:实现 ServletContextListener 接口,监听 ServletContext 的初始化和销毁事件,是 Web 上下文的 “启动器”。
  • contextConfigLocation:指定 Spring 配置文件的位置,若不配置则使用默认路径(/WEB-INF/applicationContext.xml)。

ContextLoaderListener 工作原理

ContextLoaderListener 继承 ContextLoader 类,通过重写 ServletContextListener 的回调方法,将 Web 上下文的初始化与 ServletContext 生命周期绑定。

核心源码解析
阅读全文 »

Yarn工作机制详解:从作业提交流程到资源调度全解析

YARN(Yet Another Resource Negotiator)作为 Hadoop 的资源管理中枢,负责协调集群资源并调度应用程序执行。其工作机制围绕 资源申请、任务分配、执行监控 三个核心环节展开,支持 MapReduce、Spark 等多种计算框架。本文将通过 11 个关键步骤,深度解析 YARN 的完整工作流程,揭示资源管理器、节点管理器与应用主控之间的协同机制。

YARN 核心实体与角色分工

在解析工作流程前,需明确 YARN 中的五大核心实体及其职责,它们共同支撑作业从提交到完成的全生命周期:

实体 核心职责 作用范围
客户端(Client) 提交作业、查询进度、终止作业 发起作业请求的用户节点
资源管理器(ResourceManager, RM) 全局资源管理、调度容器分配、监控应用主控 集群主节点
节点管理器(NodeManager, NM) 单节点资源管理、启动 / 监控容器、汇报节点状态 集群从节点
应用主控(ApplicationMaster, AM) 作业生命周期管理、资源申请、任务监控 每个应用程序独立实例
HDFS 存储作业资源(JAR、配置、输入数据)、共享中间结果 分布式文件系统

YARN 完整工作流程(11 步详解)

YARN 作业的执行流程可分为 作业提交、资源申请、任务启动、执行监控 四个阶段,每个阶段涉及多实体协同。以下以 MapReduce 作业为例,拆解 11 个关键步骤:

yarn的工作流程

阶段 1:作业提交(步骤 1-4)

目标:客户端将作业资源上传至 HDFS,并向 ResourceManager 发起提交请求。

步骤 1:客户端初始化作业提交
  • 用户通过 job.waitForCompletion(true) 提交 MapReduce 作业;
  • 客户端创建 YarnRunnerJobSubmitter 实例,封装作业配置(如输入路径、Map/Reduce 类);
  • 验证作业合法性(如检查输入输出路径是否存在、配置是否完整)。
阅读全文 »