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 结构来管理这些对象。

相关推荐
互联网全栈架构29 分钟前
遨游Spring AI:第一盘菜Hello World
java·人工智能·后端·spring
优秀的颜1 小时前
计算机基础知识(第五篇)
java·开发语言·分布式
BillKu1 小时前
Java严格模式withResolverStyle解析日期错误及解决方案
java
网安INF2 小时前
ElGamal加密算法:离散对数难题的安全基石
java·网络安全·密码学
AWS官方合作商3 小时前
在CSDN发布AWS Proton解决方案:实现云原生应用的标准化部署
java·云原生·aws
gadiaola3 小时前
【JVM】Java虚拟机(二)——垃圾回收
java·jvm
coderSong25686 小时前
Java高级 |【实验八】springboot 使用Websocket
java·spring boot·后端·websocket
Mr_Air_Boy7 小时前
SpringBoot使用dynamic配置多数据源时使用@Transactional事务在非primary的数据源上遇到的问题
java·spring boot·后端
豆沙沙包?7 小时前
2025年- H77-Lc185--45.跳跃游戏II(贪心)--Java版
java·开发语言·游戏
年老体衰按不动键盘8 小时前
快速部署和启动Vue3项目
java·javascript·vue