Spring的源码Spring的上下文怎么存储

Spring框架是一个广泛使用的Java框架,它提供了丰富的功能,包括依赖注入(DI)、面向切面编程(AOP)、事务管理等。而在Spring的核心功能之一------ApplicationContext,它负责管理和配置Spring的bean容器。ApplicationContext 是 Spring 容器的顶级接口,它继承自 BeanFactory,并提供了更多的功能,比如事件传播、国际化支持等。

Spring上下文的存储

Spring的上下文主要通过BeanFactoryApplicationContext 来存储和管理Bean。ApplicationContextBeanFactory 的一个扩展,提供了更多的功能。Spring的上下文一般是通过读取配置文件(如XML或注解)来初始化Bean定义的,并将它们存储在容器中。具体来说,ApplicationContext 通过以下方式存储 Bean:

  1. Bean Definition:存储了Bean的定义(即Bean的名称、类、作用域等信息)。
  2. Bean 实例 :存储了Bean的实例,当Bean被请求时,ApplicationContext 会根据其配置创建并返回一个Bean的实例。
  3. BeanFactory的实现ApplicationContext 内部实现了对 BeanFactory 的扩展,管理着一个 Bean 的注册表。

Spring的上下文通常会创建一个类似 ConcurrentHashMap 的容器来存储这些bean定义和实例。具体实现取决于 Spring 中的 BeanFactoryApplicationContext 的实现类。

Spring 上下文存储代码示例

1. 使用注解配置 Spring Bean

假设你在一个 Spring Boot 或 Spring 项目中使用注解来配置 Bean:

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}

在这个配置类中,@Configuration 注解表示这是一个配置类,@Bean 注解用于定义一个 Bean。Spring 会自动扫描这个类,并将 myBean 方法返回的实例注册为一个 Bean。

2. ApplicationContext 的实现和存储

Spring 容器通过 ApplicationContext 来管理这些 Bean。例如,AnnotationConfigApplicationContextApplicationContext 的一个实现,它用于基于注解的配置。

java 复制代码
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        // 创建 AnnotationConfigApplicationContext 容器并加载配置类
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        // 获取 myBean 实例
        MyBean myBean = context.getBean(MyBean.class);

        System.out.println(myBean);
    }
}
3. Spring Bean 存储的实现

AnnotationConfigApplicationContext 中,ApplicationContext 会通过 DefaultListableBeanFactory(它是 BeanFactory 的一个实现)来存储和管理 Bean。Spring 的 DefaultListableBeanFactory 会维护一个 Map 来存储这些 Bean 定义(BeanDefinition),然后再通过这些定义来创建 Bean 实例。

java 复制代码
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.support.GenericApplicationContext;

public class SpringContextStorageExample {
    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();
        context.register(AppConfig.class); // 注册配置类

        context.refresh(); // 刷新上下文,初始化 bean

        // 获取 bean 实例
        MyBean myBean = context.getBean(MyBean.class);
        System.out.println(myBean);
    }
}
4. DefaultListableBeanFactory 中的存储

Spring会将bean的定义存储在一个叫做 DefaultListableBeanFactory 的类中,该类实现了 BeanFactoryBeanDefinitionRegistry 接口。

java 复制代码
public class DefaultListableBeanFactory extends AbstractBeanFactory implements BeanDefinitionRegistry {
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();

    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
        beanDefinitionMap.put(beanName, beanDefinition);
    }

    @Override
    public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
        return beanDefinitionMap.get(beanName);
    }

    // 通过BeanDefinition创建bean实例
    public Object getBean(String name) throws BeansException {
        BeanDefinition beanDefinition = getBeanDefinition(name);
        return createBean(beanDefinition);
    }
}
  • beanDefinitionMap 是一个 ConcurrentHashMap,用来存储 BeanDefinition
  • BeanDefinition 存储了一个 Bean 的定义信息(例如 Bean 的类类型、构造方法等),DefaultListableBeanFactory 会根据这些定义来创建和管理 Bean 实例。
5. Bean 实例化和缓存

getBean() 方法被调用时,Spring 会检查这个 Bean 是否已经创建过。如果已经创建过,Spring 会直接从缓存中返回这个实例。Spring 容器对每个 Bean 使用不同的作用域进行管理,默认是单例模式。

java 复制代码
public class DefaultListableBeanFactory {
    private final Map<String, Object> singletonCache = new ConcurrentHashMap<>();

    public Object getBean(String name) {
        // 检查缓存中是否已经有这个 Bean 实例
        if (singletonCache.containsKey(name)) {
            return singletonCache.get(name);
        }

        // 如果没有,创建新的实例
        BeanDefinition beanDefinition = getBeanDefinition(name);
        Object bean = createBean(beanDefinition);

        // 将实例缓存到 singletonCache 中
        singletonCache.put(name, bean);
        return bean;
    }
}

总结

Spring 上下文的存储本质上是通过 ApplicationContext(具体实现类如 AnnotationConfigApplicationContext)来管理 Bean 的定义和实例。ApplicationContext 使用 BeanFactory 来管理 Bean 定义(如 BeanDefinition)和实例化,并通过缓存机制来优化性能。Spring 通过不同的 BeanFactory 实现(如 DefaultListableBeanFactory)来存储、创建和缓存 Bean。

以上示例展示了 Spring 是如何通过容器存储和管理 Bean 的,ApplicationContextBeanFactory 的实现内部细节以及它们如何通过 Map 结构来管理这些对象。

相关推荐
Asthenia04122 分钟前
深入剖析 Spring Boot 请求处理链路与 Servlet 的本质
后端
旧时光巷4 分钟前
【Flask 基础 ①】 | 路由、参数与模板渲染
后端·python·零基础·flask·web·模板渲染·路由系统
小醉你真好8 分钟前
Spring Boot 数据源配置中为什么可以不用写 driver-class-name
spring boot·后端·源代码管理
SirLancelot131 分钟前
数据结构-Set集合(一)Set集合介绍、优缺点
java·开发语言·数据结构·后端·算法·哈希算法·set
haaaaaaarry37 分钟前
Element Plus常见基础组件(一)
java·前端·javascript·vue.js
lang2015092840 分钟前
如何使用 Apache Ignite 作为 Spring 框架的缓存(Spring Cache)后端
spring·缓存·apache·ignite
歌者長門42 分钟前
做题笔记:某大讯飞真题28道
java·数据结构·算法
追逐时光者1 小时前
2 款 .NET 开源、简洁、高效的 PDF 文档操作库
后端·.net
Savvy..1 小时前
Day05 Maven
java·junit·maven·注解
Goboy1 小时前
分库分表后ID乱成一锅粥
后端·面试·架构