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

相关推荐
hrrrrb1 小时前
【Rust】所有权
开发语言·后端·rust
碎梦归途1 小时前
23种设计模式-行为型模式之状态模式(Java版本)
java·jvm·设计模式·状态模式·软考·软件设计师·行为模式
豆沙沙包?2 小时前
2025年- H16-Lc124-169.多数元素(技巧)---java版
java·开发语言
zhangxueyi3 小时前
Java实现基数排序算法
java·数据结构·算法
Another Iso4 小时前
同时启动俩个tomcat压缩版
java·tomcat
华纳云IDC服务商5 小时前
华纳云:centos如何实现JSP页面的动态加载
java·linux·centos
碎梦归途5 小时前
23种设计模式-行为型模式之访问者模式(Java版本)
java·开发语言·jvm·设计模式·软考·软件设计师·行为型模式
Demons_kirit6 小时前
LeetCode LCP40 心算挑战题解
java·数据结构·算法·leetcode·职场和发展
Jiaberrr6 小时前
uniapp 实现低功耗蓝牙连接并读写数据实战指南
java·前端·javascript·vue.js·struts·uni-app