Spring 核心技术解析【纯干货版】- V:Spring 基础模块 Spring-Context 模块精讲

Spring 框架作为 Java 开发领域最流行的框架之一,其核心模块承载了大量企业级应用开发的基础功能。在 Spring 的核心模块中,Spring-Context 模块尤为重要,它不仅提供了应用上下文的管理功能,还扩展了事件驱动、国际化支持、资源加载等功能,是构建现代化 Spring 应用程序的基石。

本篇文章将深入解析 Spring-Context 模块的核心技术,涵盖模块概述、依赖关系、主要功能、注解支持,以及事件驱动模型等方面。通过这篇文章,您可以全面掌握 Spring-Context 模块的核心知识,为开发高效、可扩展的 Spring 应用奠定坚实基础。


文章目录


1、Spring-Context 模块介绍

1.1、Spring-Context 模块概述

Spring-Context 模块,是 Spring 核心容器模块之一,它为应用程序上下文的管理提供了支持,同时也是许多其他 Spring 模块的依赖基础。

应用程序上下文,也称为 Application Context,来源于设计模式中的一个术语。在许多设计模式中,上下文通常用于隐式表示执行某个行为时所需的环境或条件。在 Spring-Context 模块中,这一抽象概念被具体实现为各种 Context 对象。

Spring-Context 模块中的 Context 是一个集中化的管理器,除了负责 Bean 的生命周期管理(如创建、初始化、销毁等),还提供了运行应用程序所需的各种服务。

1.2、Spring-Context 模块依赖

Spring-Context 模块的依赖有四个,分别是同为基础模块的 Spring-Beans 模块、Spring-Core 模块、Spring-Expression 模块和 AOP 模块中的 Spring-AOP 模块。

其中 Spring Beans 模块是对 Spring Bean 进行定义,实现 IOC 基础功能的模块。Spring-Core 是 Spring 中的基础模块,它提供了框架运行所必需的核心功能。Spring-Expression 提供对 SpEL 的支持。而 Spring-AOP 提供对 AOP 的支持。

1.3、Spring-Context 模块作用

由于 Spring-Context 模块依赖了全部的 Spring 基本模块,并在他们的基础上进一步完善相关功能,包括但不限于:资源管理、环境与配置管理、生命周期管理、校验与格式化、AOP 与声明式事务支持等内容。

本篇仅简单介绍一部分核心功能例如:应用上下文(ApplicationContext)、注解支持、事件驱动的内容。


2、ApplicationContext 的介绍

在 Spring 框架中,ApplicationContext 是最核心的接口之一,主要用于容纳和管理 Spring 容器中的所有 Bean 实例。它不仅拓展了 BeanFactory 接口,更是提供了更加丰富和灵活的功能。包括国际化支持、事件传播、AOP 支持等。

2.1、ApplicationContext 的功能与特性

下面是 ApplicationContext 的源码:

java 复制代码
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    @Nullable
    String getId();
    String getApplicationName();
    String getDisplayName();
    long getStartupDate();
    @Nullable
    ApplicationContext getParent();
    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}

它继承了 BeanFactoryMessageSourceApplicationEventPublisher 等 6 个接口。

下面是 ApplicationContext 继承的 6 个父接口的说明:

  • MessageSource 接口:用于处理信息资源的国际化,能够支持多语言和地区化功能。
  • ApplicationEventPublisher 接口:是事件发布的接口,允许在 Spring 应用中发布事件。事件可以用于解耦应用的不同组件,让它们以松耦合的方式进行交互。
  • ResourcePatternResolver 接口:继承自 ResourceLoader,提供了扩展的功能来解析资源路径和资源模式。它支持通过模式(例如 classpath:)解析并加载资源,不仅能够加载文件,还可以加载类路径上的文件、网络资源等。
  • EnvironmentCapable 接口:提供对应用程序环境的访问。
  • ListableBeanFactory 接口:继承自 BeanFactory,增强了列举和查询 Bean 的能力。它允许你列出容器中所有 Bean 的名称、类型,甚至根据类型或名称进行过滤和查找。
  • HierarchicalBeanFactory 接口:继承自 BeanFactory,引入了 Bean 工厂的分层概念。它允许 Spring 容器支持层次化的 Bean 工厂结构,使得上下文可以有父容器和子容器。

ApplicationContext 的父接口,和下面的方法定义上,我们也可以大致总结出,ApplicationContext 有着:负责管理 Bean 的生命周期、提供事件发布、国际化支持、资源加载、环境配置及自动装配等功能。

2.2、ApplicationContext 的实现

上面我们介绍了 ApplicationContext 接口的功能,接着我们来看一下它的实现,Spring 提供了多个 ApplicationContext 实现类,每个实现类适用于不同的使用场景。

以下是 ApplicationContext 的主要实现的介绍及特性:

  • ClassPathXmlApplicationContext:这是最常见的 ApplicationContext 实现之一,主要通过 XML 配置文件来加载和配置 Bean。它的实现基于 AbstractXmlApplicationContext 类,专门用于解析类路径下的 XML 配置文件,来初始化 Spring 容器。这种实现类适用于小型到中型项目,特别是在需要从类路径中加载配置文件的场景中。

    例如,假设我们有一个简单的 Spring 应用,配置文件位于 src/main/resources 目录下,可以使用 ClassPathXmlApplicationContext 来加载配置文件:

    java 复制代码
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  • FileSystemXmlApplicationContext:这个实现类可以从文件系统中加载 XML 配置文件。它适用于需要从文件系统中加载配置文件的场景,例如在开发环境中,配置文件可能位于项目的根目录或某个特定的文件夹中。使用 FileSystemXmlApplicationContext 可以方便地加载这些配置文件:

    java 复制代码
    ApplicationContext context = new FileSystemXmlApplicationContext("file:/path/to/applicationContext.xml");
  • AnnotationConfigApplicationContext:基于注解的配置而设计的实现类。它支持 Java 配置类的方式,允许通过注解(如 @Configuration, @ComponentScan, @Bean 等)来配置 Spring 容器中的 Bean。它是 Spring 4 引入的,以支持纯 Java 配置,特别适用于 Spring Boot 等需要更灵活和简洁配置的现代 Spring 应用。

    例如,假设我们有一个配置类 AppConfig,可以使用 AnnotationConfigApplicationContext 来加载配置类:

    java 复制代码
    ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  • GenericWebApplicationContext:Spring-Web 模块中提供的,是为 Web 应用设计的 ApplicationContext 实现类,继承自 GenericApplicationContext,专门用于 Spring Web 应用(例如 Spring MVC)。它结合了 Web 环境的特殊需求,提供了对 Web 组件的支持。

    GenericWebApplicationContext 通常通过 ContextLoaderListener 在应用启动时初始化:

    xml 复制代码
    // web.xml 配置
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

选择合适的 ApplicationContext 实现类需要综合考虑项目规模、配置方式、应用类型和性能需求。对于小型到中型项目,ClassPathXmlApplicationContextAnnotationConfigApplicationContext 是不错的选择,前者适合 XML 配置,后者更适合注解和 Java 配置。而在大型或复杂项目中,AnnotationConfigApplicationContext 提供了更高的灵活性和扩展性,而 Web 应用推荐使用支持 Servlet 和 JSP 配置的 GenericWebApplicationContext。如果性能是关键考虑因素,注解驱动的 AnnotationConfigApplicationContext 通常比 XML 配置的实现类更高效。总之,根据具体需求选择最合适的实现类,能更好地平衡项目的开发效率与运行性能。


3、核心注解:Bean、配置和自动扫描

3.1、@Configuration

模块:spring-context 模块。

作用:标记一个类为配置类,类似于传统 XML 配置中的 <beans> 标签,表示该类中定义的 Bean 都会被 Spring 容器管理。

使用方式:通常与 @Bean 注解一起使用,在配置类中定义 Bean。

使用示例:

java 复制代码
@Configuration
public class AppConfig {
    @Bean
    public MyService myService() {
        return new MyService();
    }
}
3.2、@Bean

模块:spring-context 模块。

作用:标记方法为 Bean 定义,用于将方法返回的对象注册到 Spring 容器中,通常配合 @Configuration 使用。

使用方式:在 @Configuration 注解标注的类中,使用 @Bean 注解将方法返回值作为 Bean 注册到容器。

3.3、@Component

模块:spring-context 模块。

作用:标记类为 Spring 的组件(Bean),Spring 会自动扫描并将其注册到容器中。@Component 是一个通用的注解,可以通过 @ComponentScan 来扫描指定包中的类。

使用示例:

java 复制代码
package com.lizhengi.service

@Component
public class MyService {
    // Service logic
}

常见衍生注解:

  • @Service:通常用于服务层的 Bean。
  • @Repository:通常用于数据访问层的 Bean,包含数据访问相关的异常转换功能。
  • @Controller:通常用于标注 Spring MVC 中的控制器。
3.4、@ComponentScan

模块:spring-context 模块。

作用:用于自动扫描指定包中的 @Component 注解类,自动将它们注册到 Spring 容器中。通常配合 @Configuration 使用。

使用方式:指定要扫描的包或包的路径,自动注册标记为 @Component@Service@Repository@Controller 等注解的类。

使用示例:

java 复制代码
@Configuration
@ComponentScan(basePackages = "com.lizhengi")
public class AppConfig {
    // 自动扫描指定包中的 Bean
}

4、事件驱动

Spring 的事件驱动模型,其实就是在 ApplicationContext 基础上加了个观察者模式。发布者负责发消息,监听者负责接收,Spring 负责中间传话。看似复杂,其实是个精简版的观察者模式,简单又高效。

观察者模式 的核心是 发布者 和 订阅者 的解耦,通过一个中间层(如事件管理器)让二者不直接依赖。Spring 的事件驱动模型 则完全复用了这一思想,ApplicationContext 扮演了 "事件管理器" 的角色,负责维护发布者和监听者之间的关系。

4.1、事件驱动核心概念及 Spring-Context 模块的实现
4.1.1、事件

事件(Event):事件是发生了某种操作或状态改变的信号。在 Spring 中,事件是 ApplicationEvent 的子类,也可以是任何自定义类。

java 复制代码
public class CustomEvent extends ApplicationEvent {
    private String message;

    public CustomEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}
4.1.2、事件发布器

事件发布器(Event Publisher):Spring 提供了 ApplicationEventPublisher 接口,用于发布事件。通常,通过注入 ApplicationEventPublisher 来发布事件:

java 复制代码
@Component
public class EventPublisher {
    private final ApplicationEventPublisher publisher;

    public EventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    public void publishCustomEvent(String message) {
        CustomEvent event = new CustomEvent(this, message);
        publisher.publishEvent(event);
    }
}
4.1.3、事件监听器

事件监听器(Event Listener):事件监听器用于处理特定类型的事件。可以通过 @EventListener 注解或者实现 ApplicationListener 接口来定义监听器:

使用 @EventListener

java 复制代码
@Component
public class EventListenerExample {
    @EventListener
    public void handleCustomEvent(CustomEvent event) {
        System.out.println("Received event - " + event.getMessage());
    }
}

实现 ApplicationListener 接口:

java 复制代码
@Component
public class CustomEventListener implements ApplicationListener<CustomEvent> {
    @Override
    public void onApplicationEvent(CustomEvent event) {
        System.out.println("Handled event - " + event.getMessage());
    }
}
4.1.4、上下文事件

Spring 自带了一些标准事件,例如:

  • ContextRefreshedEvent:容器初始化或刷新时发布。
  • ContextStartedEvent:容器调用 start() 方法时发布。
  • ContextStoppedEvent:容器调用 stop() 方法时发布。
  • ContextClosedEvent:容器关闭时发布。
4.2、使用示例

发布事件:

java 复制代码
@SpringBootApplication
public class EventDemoApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(EventDemoApplication.class, args);

        EventPublisher publisher = context.getBean(EventPublisher.class);
        publisher.publishCustomEvent("Hello, Spring Event!");
    }
}

异步监听:通过 @Async 注解,可以让事件处理在单独的线程中执行:

java 复制代码
@Component
public class AsyncEventListener {
    @Async
    @EventListener
    public void handleAsyncEvent(CustomEvent event) {
        System.out.println("Processing event asynchronously - " + event.getMessage());
    }
}

同时需要启用异步功能:

java 复制代码
@EnableAsync
@SpringBootApplication
public class EventDemoApplication { }

X、后记

在快速发展的软件开发领域,Spring 框架凭借其灵活性和强大的功能始终处于领先地位,而 Spring-Context 模块作为其核心之一,为开发者提供了丰富的功能支持。掌握 Spring-Context 的使用,不仅可以帮助我们更高效地管理 Bean 生命周期和上下文环境,还能通过事件驱动、注解配置等特性构建出更加优雅和高效的应用架构。

希望本文能够帮助您深入理解 Spring-Context 模块,并在实际开发中灵活运用。如果您对文中内容有疑问或建议,欢迎留言讨论。让我们携手前行,在技术的道路上不断探索,共同进步!

相关推荐
重生之绝世牛码1 小时前
Java设计模式 —— 【行为型模式】命令模式(Command Pattern) 详解
java·大数据·开发语言·设计模式·命令模式·设计原则
晚风_END2 小时前
node.js|浏览器插件|Open-Multiple-URLs的部署和使用,实现一键打开多个URL的强大工具
服务器·开发语言·数据库·node.js·dubbo
网络安全-杰克2 小时前
[网络安全]sqli-labs Less-4 解题详析
数据库·web安全·less
荆州克莱3 小时前
redis学习笔记(一)了解redis
spring boot·spring·spring cloud·css3·技术
加酶洗衣粉3 小时前
PostgreSQL学习笔记(二):PostgreSQL基本操作
数据库
java排坑日记3 小时前
poi-tl+kkviewfile实现生成pdf业务报告
java·pdf·word
V+zmm101344 小时前
校园约拍微信小程序设计与实现ssm+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
猿来入此小猿4 小时前
基于SpringBoot小说平台系统功能实现四
java·spring boot·毕业设计·毕业源码·在线小说阅读·在线小说平台·免费学习:猿来入此
狄加山6754 小时前
数据结构(查找算法)
数据结构·数据库·算法
sevevty-seven4 小时前
MySQL的主从复制
数据库·mysql