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:

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 的一个实现,它用于基于注解的配置。

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 实例。

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 接口。

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 使用不同的作用域进行管理,默认是单例模式。

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

你可能感兴趣的:(面试题,spring,java,后端)