Spring框架是一个广泛使用的Java框架,它提供了丰富的功能,包括依赖注入(DI)、面向切面编程(AOP)、事务管理等。而在Spring的核心功能之一------ApplicationContext
,它负责管理和配置Spring的bean容器。ApplicationContext
是 Spring 容器的顶级接口,它继承自 BeanFactory
,并提供了更多的功能,比如事件传播、国际化支持等。
Spring上下文的存储
Spring的上下文主要通过BeanFactory 和 ApplicationContext 来存储和管理Bean。ApplicationContext
是 BeanFactory
的一个扩展,提供了更多的功能。Spring的上下文一般是通过读取配置文件(如XML或注解)来初始化Bean定义的,并将它们存储在容器中。具体来说,ApplicationContext
通过以下方式存储 Bean:
- Bean Definition:存储了Bean的定义(即Bean的名称、类、作用域等信息)。
- Bean 实例 :存储了Bean的实例,当Bean被请求时,
ApplicationContext
会根据其配置创建并返回一个Bean的实例。 - BeanFactory的实现 :
ApplicationContext
内部实现了对BeanFactory
的扩展,管理着一个 Bean 的注册表。
Spring的上下文通常会创建一个类似 ConcurrentHashMap
的容器来存储这些bean定义和实例。具体实现取决于 Spring 中的 BeanFactory
和 ApplicationContext
的实现类。
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。例如,AnnotationConfigApplicationContext
是 ApplicationContext
的一个实现,它用于基于注解的配置。
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
的类中,该类实现了 BeanFactory
和 BeanDefinitionRegistry
接口。
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 的,ApplicationContext
和 BeanFactory
的实现内部细节以及它们如何通过 Map
结构来管理这些对象。