Spring理论知识(Ⅱ)——Spring核心容器模块

Spring的组成

Spring由20个核心依赖组成,这20个核心依赖可以分为6个核心模块



本篇文章着重描述Spring核心容器模块,其中包含了spring-beans,spring-core,spring-context,spring-expression-language(SpEl),spring-context-support等依赖

1. Spring核心容器

1.1 Spring核心容器的依赖简介

Spring Core Container 是 Spring 框架的核心部分,它为整个 Spring 框架提供了基础设施和基本功能。Spring Core Container 负责管理 Spring 应用中的所有组件(如 Beans)的创建、配置和生命周期,并通过依赖注入(Dependency Injection, DI)和面向切面编程(Aspect-Oriented Programming, AOP)等机制来促进松散耦合的设计。

Spring Core

核心功能模块:Spring Core 模块是整个 Spring 框架的基础,包含了依赖注入(DI)机制的实现。它定义了 Spring 的基础类和接口,如 BeanFactory 和 ApplicationContext,这些都是 Spring 应用的核心部分。

BeanFactory:BeanFactory 是 Spring 的核心接口,用于管理 Bean 的创建和配置。它提供了基本的 IoC(控制反转)功能,是所有 Spring 应用的基石。

ApplicationContext:ApplicationContext 是 BeanFactory 的一个扩展,它提供了更多的企业级功能,如事件传播、国际化、AOP 支持等。ApplicationContext 是 Spring 应用中的高级容器,用于更复杂的配置和管理。

Spring Beans

Bean 配置和管理:Spring Beans 模块用于管理和配置 Spring 应用中的 Bean。Bean 是 Spring 容器管理的对象,可以通过 XML、注解或 Java 配置类来定义和配置。

依赖注入:通过依赖注入机制,Spring 容器会自动将需要的依赖注入到 Bean 中,从而减少组件之间的耦合,使得代码更易于测试和维护。

Spring Context

ApplicationContext 扩展:Spring Context 模块是对 Core 和 Beans 模块的扩展,提供了更全面的框架功能。ApplicationContext 作为高级容器,在大型企业应用中非常常用。

注解驱动开发:Spring Context 支持注解驱动的依赖注入,可以通过注解如 @Component、@Service、@Repository 等来标识 Spring 管理的 Bean,并使用 @Autowired 来自动注入依赖。

Spring Expression Language (SpEL)

表达式语言支持:SpEL 是 Spring 提供的一种强大的表达式语言,可以在 XML 配置、注解或其他 Spring 配置中使用。SpEL 支持调用方法、访问属性、操作集合等,提供了极大的灵活性。

1.2 Spring核心容器的pom依赖

xml 复制代码
        <!--Spring核心容器-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

spring-core

Spring Core 是 Spring 框架的核心模块,提供了所有其他 Spring 模块的基础功能。

1. 核心工具类:

StringUtils:处理字符串的工具类。

ObjectUtils:提供对象相关的工具方法。

ClassUtils:用于处理类加载和反射的实用方法。

CollectionUtils:用于处理集合的工具类。

Assert:提供常用的断言方法,方便进行前置条件的验证。

这些工具类在整个 Spring 框架和开发中广泛使用,提供了对基本操作的简化。

2. 资源抽象(Resource Abstraction):

Resource 接口 以及相关实现类(如 ClassPathResource、FileSystemResource、UrlResource 等),提供了一套统一的 API 来访问不同类型的资源(例如文件系统中的文件、类路径资源、URL 资源等)。

这种抽象使得应用程序可以轻松地在不同的资源位置之间切换,而不必修改业务逻辑。

3. 类型转换系统(Type Conversion System):

ConversionService 接口 提供了对类型转换的支持,允许在应用中轻松地进行类型转换。这在处理配置文件中的属性值或者注入时尤为重要。

还包括 PropertyEditor 支持,允许在需要时将字符串转换为复杂对象。

4. 环境抽象(Environment Abstraction):

Environment 接口 及其实现类,提供了对环境变量、系统属性和外部化配置的访问和管理。

PropertySource 和 PropertyResolver 接口帮助解析和管理配置属性,这些功能对于支持外部化配置和环境感知的应用程序至关重要。

5. 日志支持:

提供了对多种日志框架(如 Log4j、SLF4J)的抽象支持,允许应用程序在不同的日志实现之间切换而无需更改代码。

这里需要重点说明:spring-core本身并不提供对多种日志框架的支持,而是通过引入spring-jcl完成了这个功能;另外我们观察spring-jcl包的结构

包名居然是apache.commons.logging!这是因为spring团队对common.logging 进行了重写,所以包名还保留之前的apache.commons.logging

JCL的全称为: Jakarta commons-logging, 是apache公司提供的一个抽象的日志框架, 并不提供日志功能,若需要使用具体的日志则需要添加依赖的jar包,但是它没有维护了,所以spring团队自己重写推出了一个spring-jcl

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>5.0.2.RELEASE</version>
  <name>Spring Core</name>
  <description>Spring Core</description>
  <url>https://github.com/spring-projects/spring-framework</url>
  <organization>
    <name>Spring IO</name>
    <url>http://projects.spring.io/spring-framework</url>
  </organization>
  <licenses>
    <license>
      <name>Apache License, Version 2.0</name>
      <url>http://www.apache.org/licenses/LICENSE-2.0</url>
      <distribution>repo</distribution>
    </license>
  </licenses>
  <developers>
    <developer>
      <id>jhoeller</id>
      <name>Juergen Hoeller</name>
      <email>jhoeller@pivotal.io</email>
    </developer>
  </developers>
  <scm>
    <connection>scm:git:git://github.com/spring-projects/spring-framework</connection>
    <developerConnection>scm:git:git://github.com/spring-projects/spring-framework</developerConnection>
    <url>https://github.com/spring-projects/spring-framework</url>
  </scm>
  <issueManagement>
    <system>Jira</system>
    <url>https://jira.springsource.org/browse/SPR</url>
  </issueManagement>
  <dependencies>
    <dependency>
      <groupId>io.netty</groupId>
      <artifactId>netty-buffer</artifactId>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>io.projectreactor</groupId>
      <artifactId>reactor-core</artifactId>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>io.reactivex.rxjava2</groupId>
      <artifactId>rxjava</artifactId>
      <version>2.1.6</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>io.reactivex</groupId>
      <artifactId>rxjava</artifactId>
      <version>1.3.4</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>io.reactivex</groupId>
      <artifactId>rxjava-reactive-streams</artifactId>
      <version>1.2.1</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>net.sf.jopt-simple</groupId>
      <artifactId>jopt-simple</artifactId>
      <version>5.0.4</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.13</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-reflect</artifactId>
      <version>1.1.61</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-stdlib</artifactId>
      <version>1.1.61</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jcl</artifactId>
      <version>5.0.2.RELEASE</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>io.projectreactor</groupId>
        <artifactId>reactor-bom</artifactId>
        <version>Bismuth-SR4</version>
        <scope>import</scope>
        <type>pom</type>
      </dependency>
      <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-bom</artifactId>
        <version>4.1.17.Final</version>
        <scope>import</scope>
        <type>pom</type>
      </dependency>
    </dependencies>
  </dependencyManagement>
</project>

spring-beans

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.springframework</groupId>
  <artifactId>spring-beans</artifactId>
  <version>5.0.2.RELEASE</version>
  <name>Spring Beans</name>
  <description>Spring Beans</description>
  <url>https://github.com/spring-projects/spring-framework</url>
  <organization>
    <name>Spring IO</name>
    <url>http://projects.spring.io/spring-framework</url>
  </organization>
  <licenses>
    <license>
      <name>Apache License, Version 2.0</name>
      <url>http://www.apache.org/licenses/LICENSE-2.0</url>
      <distribution>repo</distribution>
    </license>
  </licenses>
  <developers>
    <developer>
      <id>jhoeller</id>
      <name>Juergen Hoeller</name>
      <email>jhoeller@pivotal.io</email>
    </developer>
  </developers>
  <scm>
    <connection>scm:git:git://github.com/spring-projects/spring-framework</connection>
    <developerConnection>scm:git:git://github.com/spring-projects/spring-framework</developerConnection>
    <url>https://github.com/spring-projects/spring-framework</url>
  </scm>
  <issueManagement>
    <system>Jira</system>
    <url>https://jira.springsource.org/browse/SPR</url>
  </issueManagement>
  <dependencies>
    <dependency>
      <groupId>javax.inject</groupId>
      <artifactId>javax.inject</artifactId>
      <version>1</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.codehaus.groovy</groupId>
      <artifactId>groovy-all</artifactId>
      <version>2.4.13</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-reflect</artifactId>
      <version>1.1.61</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-stdlib</artifactId>
      <version>1.1.61</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>5.0.2.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.yaml</groupId>
      <artifactId>snakeyaml</artifactId>
      <version>1.19</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
  </dependencies>
</project>

我们可以看到其中包含了spring-core的依赖

spring-beans在Spring 的 IoC(Inversion of Control,控制反转)容器中起着至关重要的作用。这个包主要用于管理和配置应用程序中的 Bean,它提供了 Bean 的定义、创建、配置和管理的功能,是 Spring IoC 容器的基础。

1. Bean定义与管理

BeanDefinition 接口:定义了 Bean 的元数据,如类名、作用域scope、属性依赖,延迟加载等。所有的 Bean 都有一个对应的 BeanDefinition,用来描述该 Bean 的配置和依赖关系。

BeanFactory 接口(最重要的接口):Spring IoC 容器的基础接口,定义了 Bean 的创建、获取、销毁等基本操作。

ApplicationContext 是 BeanFactory 的一个更高级的子接口,提供了更多功能。

任何实现了BeanFactory接口的实现类,都可以被认为是一个Spring IOC容器

BeanFactory是spring中提供的最简单最基本的容器;

BeanFactory只提供了IOC/DI的功能。

这个容器中最主要个方法就是getBean()方法

DefaultListableBeanFactory:BeanFactory 的常用实现类,支持 Bean 的自动装配和多种 Bean 定义。

2. Bean生命周期管理

BeanFactory已经提供了基本的bean生命周期管理的功能,还有一些其他接口

BeanPostProcessor 接口

提供了对 Bean 的初始化前后进行处理的机制。开发者可以通过实现这个接口,在 Bean 的创建过程中加入自定义的逻辑。

java 复制代码
package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;

public interface BeanPostProcessor {


	// 初始化前执行
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	// 初始化后执行
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}
InitializingBean 接口

定义了一个 afterPropertiesSet() 方法,用于在Bean的属性设置完毕后执行自定义的初始化逻辑

java 复制代码
package org.springframework.beans.factory;

public interface InitializingBean {

	// 初始化时执行
	void afterPropertiesSet() throws Exception;

}
SmartInitializingSingleton接口

提供在所有单例Bean实例化完成后的回调机制

java 复制代码
public interface SmartInitializingSingleton {

	/**
	 * Invoked right at the end of the singleton pre-instantiation phase,
	 * with a guarantee that all regular singleton beans have been created
	 * already. {@link ListableBeanFactory#getBeansOfType} calls within
	 * this method won't trigger accidental side effects during bootstrap.
	 * <p><b>NOTE:</b> This callback won't be triggered for singleton beans
	 * lazily initialized on demand after {@link BeanFactory} bootstrap,
	 * and not for any other bean scope either. Carefully use it for beans
	 * with the intended bootstrap semantics only.
	 */

	// 
	void afterSingletonsInstantiated();

}
DisposableBean 接口

定义了 destroy() 方法,允许在 Bean 被销毁时执行自定义的清理逻辑。

java 复制代码
package org.springframework.beans.factory;

public interface DisposableBean {

	void destroy() throws Exception;

}
BeanFactoryPostProcessor接口

用于在BeanFactory创建后,对其中的Bean定义进行修改。

@FunctionalInterface表示这是一个函数式接口,用匿名内部类实现接口时可以替换为Lambda表达式

java 复制代码
@FunctionalInterface
public interface BeanFactoryPostProcessor {

	/**
	 * Modify the application context's internal bean factory after its standard
	 * initialization. All bean definitions will have been loaded, but no beans
	 * will have been instantiated yet. This allows for overriding or adding
	 * properties even to eager-initializing beans.
	 * @param beanFactory the bean factory used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}
3. 依赖注入

PropertyAccessor 和 BeanWrapper 接口:提供了对 Bean 属性的设置和访问的功能,支持属性的自动注入。

AutowireCapableBeanFactory:扩展了 BeanFactory 接口,支持自动装配的 Bean 工厂,可以自动注入依赖。

4. 属性解析与配置

PropertyEditor 接口:用于将属性值从一种格式转换为另一种格式,通常用于配置文件中的字符串与实际类型(如数字、布尔值、日期等)之间的转换。

CustomEditorConfigurer:允许在 Spring 容器中注册自定义的 PropertyEditor,用于自定义属性的转换规则。

5. 事件处理

ApplicationEvent 和 ApplicationListener 接口:用于在 Spring 容器中发布和监听事件。spring-beans 包提供了事件发布和处理的基础机制,而更高级的事件处理通常由 ApplicationContext 来实现。

spring-context和spring-context-support

1. pom依赖分析

spring-context,核心是更高级的bean生命周期管理:ApplicationContext接口(BeanFactory的子接口)

xml 复制代码
<dependency>
      <groupId>javax.annotation</groupId>
      <artifactId>javax.annotation-api</artifactId>
      <version>1.3.1</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>javax.ejb</groupId>
      <artifactId>javax.ejb-api</artifactId>
      <version>3.2</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>javax.enterprise.concurrent</groupId>
      <artifactId>javax.enterprise.concurrent-api</artifactId>
      <version>1.0</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>javax.inject</groupId>
      <artifactId>javax.inject</artifactId>
      <version>1</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>javax.interceptor</groupId>
      <artifactId>javax.interceptor-api</artifactId>
      <version>1.2.1</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>javax.money</groupId>
      <artifactId>money-api</artifactId>
      <version>1.0.1</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>javax.validation</groupId>
      <artifactId>validation-api</artifactId>
      <version>1.1.0.Final</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>javax.xml.ws</groupId>
      <artifactId>jaxws-api</artifactId>
      <version>2.3.0</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>joda-time</groupId>
      <artifactId>joda-time</artifactId>
      <version>2.9.9</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.13</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.beanshell</groupId>
      <artifactId>bsh</artifactId>
      <version>2.0b5</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.codehaus.groovy</groupId>
      <artifactId>groovy-all</artifactId>
      <version>2.4.13</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>5.4.2.Final</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-reflect</artifactId>
      <version>1.1.61</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-stdlib</artifactId>
      <version>1.1.61</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.0.2.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>5.0.2.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>5.0.2.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-expression</artifactId>
      <version>5.0.2.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-instrument</artifactId>
      <version>5.0.2.RELEASE</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>

主要包含了spring-core,spring-beans,spring-expression,spring-instrument依赖

spring-context-support,主要是一些工具类,增强spring-context。包含本地缓存,spring事务等

xml 复制代码
<dependencies>
    <dependency>
      <groupId>com.github.ben-manes.caffeine</groupId>
      <artifactId>caffeine</artifactId>
      <version>2.6.0</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>javax.activation</groupId>
      <artifactId>activation</artifactId>
      <version>1.1.1</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>javax.cache</groupId>
      <artifactId>cache-api</artifactId>
      <version>1.0.0</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>javax.mail</groupId>
      <artifactId>javax.mail-api</artifactId>
      <version>1.6.0</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>net.sf.ehcache</groupId>
      <artifactId>ehcache</artifactId>
      <version>2.10.4</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.codehaus.fabric3.api</groupId>
      <artifactId>commonj</artifactId>
      <version>1.1.0</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.freemarker</groupId>
      <artifactId>freemarker</artifactId>
      <version>2.3.27-incubating</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.quartz-scheduler</groupId>
      <artifactId>quartz</artifactId>
      <version>2.3.0</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>5.0.2.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.2.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>5.0.2.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.0.2.RELEASE</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.0.2.RELEASE</version>
      <scope>compile</scope>
      <optional>true</optional>
    </dependency>
  </dependencies>
spring-context的主要内容分析

spring-context指的是spring上下文
Spring Context 你真的懂了吗

在计算机系统中,进程执行时有进程上下文,如果进程在执行的过程中遇到了中断,CPU 会从用户态切换为内核态(当然这个过程用户进程是感知不到的,由硬件来实现的),此时进程处于的进程上下文会被切换到中断上下文中,从而可以根据中断号去执行相应的中断程序。

通过上面这个例子我们可以发现,进程在执行程序(不管是用户程序,还是内核中的中断程序)时,都会依赖一个上下文,这个上下文由多种数据结构组成,可以提供我们运行时需要的一些数据和保存运行时的一些数据。那其实 spring-context 就可以理解对一个程序运行时所需要的一些数据结构的抽象表达。

上文中我们可以很清晰的看到caffeine的使用,用于本地缓存

创建好的bean会被存放到spring-context中定义的数据结构当中,也会存储在缓存当中

spring-context主要包括:

DefaultListableBeanFactory

这就是大家常说的 ioc 容器,它里面有很多 map、list。spring 帮我们创建的 singleton 类型的 bean 就存放在其中一个 map 中。我们定义的监听器(ApplicationListener)也被放到一个 Set 集合中。

BeanDefinitionRegistry

把一个 BeanDefinition 放到 beanDefinitionMap。

AnnotatedBeanDefinitionReader

针对 AnnotationConfigApplicationContext 而言。一个 BeanDefinition 读取器。

扩展点集合

存放 spring 扩展点(主要是 BeanFactoryPostProcessor、BeanPostProcessor)接口的 list 集合。

BeanFactory和ApplicationContext的联系
java 复制代码
package org.springframework.context;

import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.lang.Nullable;

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;

}

ListableBeanFactory接口继承了BeanFactory接口,所以ApplicationContext本质上是BeanFactory的孙子接口

ApplicationContext接口:Spring Context模块定义了ApplicationContext接口,该接口扩展自BeanFactory接口。通过ApplicationContext接口,可以获得更丰富的功能和特性,如国际化支持、事件发布机制、资源加载、AOP支持等。ApplicationContext接口是Spring应用程序的主要接口,它扩展了BeanFactory接口,提供了更高级别的功能和集成。

配置加载:Spring Context模块支持从多种配置源加载配置信息,包括XML配置文件、Java注解和Java代码方式等。通过Spring Core的支持,它可以解析和加载这些配置信息,并在IoC容器中创建相应的对象。

Bean的管理和生命周期:Spring Context模块通过扩展Spring Core,提供了更灵活和强大的Bean的管理和生命周期管理功能。它可以自动检测和管理Bean的依赖关系,完成依赖注入,并在合适的时机执行Bean的初始化和销毁操作。

java 复制代码
package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;


public interface BeanFactory {


	String FACTORY_BEAN_PREFIX = "&";
	
	Object getBean(String name) throws BeansException;

	<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;

	Object getBean(String name, Object... args) throws BeansException;

	<T> T getBean(Class<T> requiredType) throws BeansException;

	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

	boolean containsBean(String name);
	
	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

	boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
	
	@Nullable
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;
	
	String[] getAliases(String name);

}

BeanFactory不支持基于注解的依赖注入,只能用xml文件

java 复制代码
public class BeanFactoryWithClassPathResourceTest {

    @Test
    public void createBeanFactoryAndCheckEmployeeBean() {
        Resource res = new ClassPathResource("beanfactory-example.xml");
        BeanFactory factory = new XmlBeanFactory(res);
        Employee emp = (Employee) factory.getBean("employee");

        assertTrue(factory.isSingleton("employee"));
        assertTrue(factory.getBean("employee") instanceof Employee);
        assertTrue(factory.isTypeMatch("employee", Employee.class));
        assertTrue(factory.getAliases("employee").length > 0);
    }
}

Spring Expression Language (SpEL)

spring-expression的pom依赖
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.springframework</groupId>
  <artifactId>spring-expression</artifactId>
  <version>5.0.2.RELEASE</version>
  <name>Spring Expression Language (SpEL)</name>
  <description>Spring Expression Language (SpEL)</description>
  <url>https://github.com/spring-projects/spring-framework</url>
  <organization>
    <name>Spring IO</name>
    <url>http://projects.spring.io/spring-framework</url>
  </organization>
  <licenses>
    <license>
      <name>Apache License, Version 2.0</name>
      <url>http://www.apache.org/licenses/LICENSE-2.0</url>
      <distribution>repo</distribution>
    </license>
  </licenses>
  <developers>
    <developer>
      <id>jhoeller</id>
      <name>Juergen Hoeller</name>
      <email>jhoeller@pivotal.io</email>
    </developer>
  </developers>
  <scm>
    <connection>scm:git:git://github.com/spring-projects/spring-framework</connection>
    <developerConnection>scm:git:git://github.com/spring-projects/spring-framework</developerConnection>
    <url>https://github.com/spring-projects/spring-framework</url>
  </scm>
  <issueManagement>
    <system>Jira</system>
    <url>https://jira.springsource.org/browse/SPR</url>
  </issueManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>5.0.2.RELEASE</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</project>

我们可以看到,spring-expression的pom依赖只有一个:spring-core

spring-expression简介

SpEL(Spring Expression Language)是Spring框架中用于表达式语言的一种方式。它类似于其他编程语言中的表达式语言,用于在运行时计算值或执行特定任务。

SpEL提供了一种简单且强大的方式来访问和操作对象的属性、调用对象的方法,以及实现运算、条件判断等操作。它可以被用于XML和注解配置中,可以用于许多Spring框架中的特性,如依赖注入、AOP、配置文件等。

SpEL表达式可以在字符串中进行定义,使用特殊的语法和符号来表示特定的操作。例如,可以使用 ${expression}来表示一个SpEL表达式,其中expression是具体的SpEL语句

SpEL支持各种操作和函数,包括算术运算、逻辑运算、条件判断、正则表达式匹配、集合操作等。它还支持访问上下文中的变量和参数,以及调用对象的方法

Spring-SpEL表达式超级详细使用全解

这些内容可以在后续的spring-boot中,application.yaml中得到体现

相关推荐
计算机徐师兄24 分钟前
Java基于SSM框架的无中介租房系统小程序【附源码、文档】
java·微信小程序·小程序·无中介租房系统小程序·java无中介租房系统小程序·无中介租房微信小程序
源码哥_博纳软云25 分钟前
JAVA智慧养老养老护理帮忙代办陪诊陪护小程序APP源码
java·开发语言·微信小程序·小程序·微信公众平台
忒可君1 小时前
C# winform 报错:类型“System.Int32”的对象无法转换为类型“System.Int16”。
java·开发语言
斌斌_____2 小时前
Spring Boot 配置文件的加载顺序
java·spring boot·后端
路在脚下@2 小时前
Spring如何处理循环依赖
java·后端·spring
一个不秃头的 程序员2 小时前
代码加入SFTP JAVA ---(小白篇3)
java·python·github
丁总学Java2 小时前
--spring.profiles.active=prod
java·spring
上等猿3 小时前
集合stream
java
java1234_小锋3 小时前
MyBatis如何处理延迟加载?
java·开发语言
菠萝咕噜肉i3 小时前
MyBatis是什么?为什么有全自动ORM框架还是MyBatis比较受欢迎?
java·mybatis·框架·半自动