Spring 核心容器
Spring 核心容器(Core Container)是 Spring 框架的基础组件之一。它负责创建和管理应用程序中的 Bean。Spring 提供了强大的 IoC(控制反转)和 DI(依赖注入)功能,使得应用程序的组件可以解耦合,提高代码的可维护性和测试性。
1.Spring 核心容器概述:
2.1 BeanFactory 和 ApplicationContext
BeanFactory
是 Spring 容器的根接口,提供了最基本的 Bean 创建和管理功能。它负责实例化、配置和管理 bean。
ApplicationContext
是 BeanFactory
的扩展,提供了更多功能,如国际化、事件发布、AOP 等。ApplicationContext
是大多数应用程序使用的容器接口。
2.2 BeanDefinition
BeanDefinition
是一个描述 Bean 的元数据的类。它包含了 Bean 的类型、作用域、构造函数参数、属性等信息。Spring 容器通过解析 BeanDefinition
来创建和配置 Bean。
2.3 主要实现类
DefaultListableBeanFactory
:是BeanFactory
的默认实现,负责管理 Bean 的创建和依赖注入。AbstractApplicationContext
:是ApplicationContext
的抽象实现,提供了容器初始化、刷新和关闭等功能。
2.Spring
既然BeanFactory是我们容器最核心的,那我们来看看他是什么样的?
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
//这个方法通过Class类型来获取某个类型的bean的ObjectProvider,用于懒加载或者多次获取bean。
<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
BeanFactory很简单就一些定义获取bean的和判断bean类型的方法,那我们再看看子类DefaultListableBeanFactory是怎么实现的?先来看看它的类图:
AbstractAutowireCapableBeanFactory
这是
DefaultListableBeanFactory
的直接父类,提供了自动注入、bean 创建等关键功能。它实现了 Spring 的依赖注入机制,并负责管理 bean 的生命周期(例如初始化、销毁)。ConfigurableListableBeanFactory
DefaultListableBeanFactory
实现了ConfigurableListableBeanFactory
接口,这赋予它对 bean 的全部控制能力,包括预加载、依赖解析、bean 定义的访问和管理等。BeanDefinitionRegistry
它实现了
BeanDefinitionRegistry
接口,允许通过注册表方式管理和维护BeanDefinition
,这是 Spring 管理 bean 定义的核心接口。先来看看其字段
@Nullable private static Class<?> javaxInjectProviderClass; //这是一个静态的 Map,用于存储可序列化的 DefaultListableBeanFactory 实例 private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories; @Nullable private String serializationId; //这是一个布尔值,表示是否允许覆盖已有的 BeanDefinition。默认情况下设置为 true,意味着当新的 BeanDefinition 被注册时,如果名称相同的 bean 定义已经存在,新的定义会覆盖旧的定义。这个配置可以在应用程序需要严格控制 bean 定义时关闭,以防止意外覆盖 private boolean allowBeanDefinitionOverriding = true; //这是一个布尔值,表示是否允许 Spring 容器在创建 bean 之前加载类。默认设置为 true,表示容器在启动时可以预加载一些 bean 类,通常用于提升性能。但是,如果设置为 false,容器会延迟加载类,直到它们第一次被实际需要时再加载。这对于处理某些类加载问题或性能调优有帮助 private boolean allowEagerClassLoading = true; @Nullable //用于对 bean 的依赖项进行排序 private Comparator<Object> dependencyComparator; //用于决定某个 bean 是否是自动注入的候选对象 private AutowireCandidateResolver autowireCandidateResolver; //这个 Map 保存了可解析的依赖项,通常是一些基础设施类的对象 private final Map<Class<?>, Object> resolvableDependencies; //用于存储所有已注册的 BeanDefinition。通过 beanName 作为键,它可以快速找到相应的 BeanDefinition。这是容器管理和查找 bean 定义的基础。 private final Map<String, BeanDefinition> beanDefinitionMap; //这个 Map 用于存储合并后的 BeanDefinition,即当一个 bean 继承了其他 BeanDefinition 时,Spring 会将其合并。BeanDefinitionHolder 包含了 BeanDefinition 以及一些额外的元数据信息。这种合并后的 BeanDefinition 是用于实际创建 bean 实例的。 private final Map<String, BeanDefinitionHolder> mergedBeanDefinitionHolders; //这个 Map 按类型保存所有已注册的 bean 名称。键是 bean 的类型,值是这个类型对应的所有 bean 名称的数组。这使得 Spring 容器可以通过类型快速查找所有匹配的 bean 名称。 private final Map<Class<?>, String[]> allBeanNamesByType; //只存储单例 bean 的名称 private final Map<Class<?>, String[]> singletonBeanNamesByType; //这是一个存储所有已注册的 bean 名称的 List private volatile List<String> beanDefinitionNames; //这是一个存储手动注册的单例 bean 名称的 Set。手动注册的单例是指通过 registerSingleton 方法直接注入到容器中的 bean,而不是通过 BeanDefinition 创建的 bean。它也是 volatile 的,确保在并发环境下的安全访问 private volatile Set<String> manualSingletonNames; @Nullable //这是一个缓存字段,用于存储 "冻结" 的 bean 名称数组。冻结状态表示容器已经准备好进行 bean 创建,所有的 BeanDefinition 都不能再被修改 private volatile String[] frozenBeanDefinitionNames; //这是一个布尔值,表示容器的配置是否已经冻结。冻结配置意味着所有 BeanDefinition 都已经加载完毕,容器进入了只读模式。冻结配置后,容器会跳过许多不必要的检查和处理,从而提高性能。 private volatile boolean configurationFrozen;
既然来了解beanfactory我们先来看看注册beandefinition这个方法:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
// 验证该 BeanDefinition 的合法性,比如是否有构造函数、属性等配置问题
if (beanDefinition instanceof AbstractBeanDefinition abd) {
try {
abd.validate();
} catch (BeanDefinitionValidationException var8) {
BeanDefinitionValidationException ex = var8;
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex);
}
}
// DefaultListableBeanFactory 定义了 private final Map<String, BeanDefinition> beanDefinitionMap;
BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
// 如果该 BeanDefinition 已经存在,处理覆盖的情况
if (existingDefinition != null) {
//就是看allowBeanDefinitionOverriding这个值默认为true
if (!this.isBeanDefinitionOverridable(beanName)) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
// 如果现有的定义的角色小于新的定义,记录覆盖信息
if (existingDefinition.getRole() < beanDefinition.getRole()) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
// // 如果新的定义和现有定义不同,输出调试日志,表示进行了覆盖
} else if (!beanDefinition.equals(existingDefinition)) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
// 如果新的定义与现有定义完全相同,输出 trace 日志,表示没有实际改变
} else if (this.logger.isTraceEnabled()) {
this.logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]");
}
// 将新的 beanDefinition 覆盖到 map 中
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
// 如果当前 bean 名称是一个别名(alias),则处理别名冲突
if (this.isAlias(beanName)) {
String aliasedName = this.canonicalName(beanName);
// 检查别名的目标 bean 是否允许覆盖
if (!this.isBeanDefinitionOverridable(aliasedName)) {
// 如果别名已经存在 BeanDefinition,则抛出异常
if (this.containsBeanDefinition(aliasedName)) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, this.getBeanDefinition(aliasedName));
}
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition for bean '" + beanName + "' since there is already an alias for bean '" + aliasedName + "' bound.");
}
// 删除别名
this.removeAlias(beanName);
}
// 检查容器是否已经开始创建 bean(即容器是否已经启动),如果已经启动则进行同步操作
if (this.hasBeanCreationStarted()) {
synchronized(this.beanDefinitionMap) {
// 将新的 BeanDefinition 放入 beanDefinitionMap 中
this.beanDefinitionMap.put(beanName, beanDefinition);
// 创建一个新的 list 并添加新的 beanName,避免并发问题
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
// 删除手动注册的单例
this.removeManualSingletonName(beanName);
}
} else {
// 如果容器还没有启动,直接将 beanDefinition 放入 map 中并添加到 list 中
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.removeManualSingletonName(beanName);
}
// 冻结 beanDefinitionNames 的缓存,表示该集合已经被更新
this.frozenBeanDefinitionNames = null;
}
// 如果没有旧的定义,并且当前 bean 不是单例,检查是否需要清空类型缓存
if (existingDefinition == null && !this.containsSingleton(beanName)) {
// 如果容器已经冻结了配置,则清理按类型的缓存
if (this.isConfigurationFrozen()) {
this.clearByTypeCache();
}
} else {
// 如果存在旧的定义,重置该 bean 的定义
this.resetBeanDefinition(beanName);
}
}
参数验证与 BeanDefinition 验证:
Assert.hasText(beanName)
和Assert.notNull(beanDefinition)
用来验证参数的合法性。- 如果
beanDefinition
是AbstractBeanDefinition
的实例(通常是,因为大多数BeanDefinition
是其子类),调用validate()
方法对 bean 定义进行合法性验证。
处理已有 BeanDefinition 的覆盖:
如果当前已经存在一个同名的BeanDefinition,则会进行一系列检查:
是否允许覆盖现有的 bean 定义,如果不允许则抛出异常。
如果新旧定义不相同,则输出不同级别的日志信息。
将新的定义覆盖旧的定义。
别名处理:
- 如果
beanName
是一个别名,则检查别名所指向的 bean,避免冲突。 - 如果有别名冲突,删除该别名。
容器状态检查:
- 如果容器已经开始创建 bean(说明容器正在运行),那么需要对
beanDefinitionMap
进行同步操作,以避免并发问题。 - 如果容器还未启动,则直接更新
beanDefinitionMap
和beanDefinitionNames
。
缓存与配置冻结:
- 如果当前容器配置已经冻结(
isConfigurationFrozen()
),则清理按类型缓存。 - 如果已经存在旧定义或是单例 bean,则调用
resetBeanDefinition()
重置该 bean 定义。
再来看看BeanDefinition的字段:
private volatile Object beanClass;
// 用于保存 bean 的类信息。它可以是 Class 对象,也可以是类名字符串。使用 volatile 以确保线程安全。
@Nullable
private String scope;
// 描述 bean 的作用域。可能的值包括 "singleton"(默认)和 "prototype" 等。如果为 null,表示使用默认的 singleton 作用域。
private boolean abstractFlag;
// 指示这个 bean 定义是否是抽象的。如果为 true,则这个 bean 不能被实例化,只能被子类继承。
@Nullable
private Boolean lazyInit;
// 表示是否懒加载。如果为 true,Spring 容器会在第一次请求时才初始化该 bean;否则在容器启动时初始化。
private int autowireMode;
// 自动装配模式,表示依赖注入的方式。可能的值包括 AutowireCapableBeanFactory.NO_AUTOWIRE(不自动装配)、BY_NAME(通过名称自动装配)、BY_TYPE(通过类型自动装配)等。
private int dependencyCheck;
// 检查依赖项的模式,可能的值包括 NONE(不检查依赖)、OBJECTS、SIMPLE(检查简单属性,如基本类型和字符串)等。
@Nullable
private String[] dependsOn;
// 该 bean 所依赖的其他 bean 名称列表。Spring 容器会确保这些依赖先初始化。
private boolean autowireCandidate;
// 标识该 bean 是否是自动装配的候选者。如果为 false,则该 bean 不会在自动装配中被考虑。
private boolean primary;
// 如果容器中有多个相同类型的 bean,primary 表示是否优先使用这个 bean。true 表示优先使用。
private final Map<String, AutowireCandidateQualifier> qualifiers;
// 存储用于自动装配限定的条件,通过这些限定符可以进一步指定自动装配的细节。
@Nullable
private Supplier<?> instanceSupplier;
// 用于提供 bean 的实例化逻辑的 Supplier。可以通过这个 Supplier 提供自定义的实例化逻辑。
private boolean nonPublicAccessAllowed;
// 是否允许访问非 public 的构造函数和方法。如果为 true,Spring 容器可以通过反射访问非 public 的构造函数和方法。
private boolean lenientConstructorResolution;
// 是否宽松地解析构造函数。如果为 true,Spring 容器在找不到完全匹配的构造函数时会尝试使用最接近的构造函数。
@Nullable
private String factoryBeanName;
// 指定创建这个 bean 的工厂 bean 名称。如果该 bean 是通过工厂 bean 创建的,那么会存储工厂 bean 的名称。
@Nullable
private String factoryMethodName;
// 指定工厂 bean 用于创建这个 bean 的工厂方法名。
@Nullable
private ConstructorArgumentValues constructorArgumentValues;
// 构造函数参数的值,用于在创建 bean 时传递给构造函数。
@Nullable
private MutablePropertyValues propertyValues;
// 用于存储 bean 的属性值,这些属性会通过 setter 方法或者字段注入到 bean 中。
private MethodOverrides methodOverrides;
// 代表方法的重写信息,主要用于支持运行时方法替换,例如通过 `lookup-method` 和 `replace-method` 标签配置的行为。
@Nullable
private String[] initMethodNames;
// 定义 bean 的初始化方法名称列表。Spring 会在 bean 创建之后调用这些方法。
@Nullable
private String[] destroyMethodNames;
// 定义 bean 的销毁方法名称列表。Spring 会在 bean 销毁之前调用这些方法。
private boolean enforceInitMethod;
// 是否强制执行初始化方法。如果为 true,初始化方法必须存在,否则抛出异常。
private boolean enforceDestroyMethod;
// 是否强制执行销毁方法。如果为 true,销毁方法必须存在,否则抛出异常。
private boolean synthetic;
// 表示这个 bean 是否是框架内部使用的合成 bean。如果为 true,表明这是一个特殊的 bean,通常不会被应用程序直接使用。
private int role;
// bean 的角色,可能的值包括 ROLE_APPLICATION(应用程序定义的 bean)、ROLE_SUPPORT(部分内部支持 bean)、ROLE_INFRASTRUCTURE(完全由框架使用的内部 bean)。
@Nullable
private String description;
// bean 的描述信息,通常用于文档化目的。
@Nullable
private Resource resource;
// bean 定义的来源资源,用于描述 bean 是从哪里加载的(例如 XML 文件或注解配置类)。
```java
//手动创建BeanDefinition
// 创建一个 GenericBeanDefinition
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(MyBean.class); // 设置 bean 的类
beanDefinition.setScope("singleton"); // 设置作用域(例如 singleton)
beanDefinition.getPropertyValues().add("name", "Manual Bean"); // 设置属性值
```java
// 通过 BeanDefinitionBuilder 创建一个 BeanDefinition
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyBean.class);
// 添加属性值(可以通过 setter 方法注入)
builder.addPropertyValue("name", "Test Bean");
// 设置自动装配模式(例如:按类型自动装配)
builder.setAutowireMode(BeanDefinition.AUTOWIRE_BY_TYPE);
// 设置作用域为 prototype
builder.setScope("prototype");
// 创建 BeanDefinition
BeanDefinition beanDefinition = builder.getBeanDefinition();
模仿实现一个beanfactory:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Bean {
}
```
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
}
```
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Configuration {
}
```java
public class BeanDefinition {
private Class<?> beanClass;
private Method factoryMethod;
public BeanDefinition(Class<?> beanClass) {
this.beanClass = beanClass;
}
public BeanDefinition(Class<?> beanClass, Method factoryMethod) {
this.beanClass = beanClass;
this.factoryMethod = factoryMethod;
}
public Class<?> getBeanClass() {
return beanClass;
}
public Method getFactoryMethod() {
return factoryMethod;
}
}
```
@Component
public class MyRepository {
}
```java
@Component
public class MyService {
private final MyRepository myRepository;
public MyService(MyRepository myRepository) {
this.myRepository = myRepository;
}
public void performService() {
System.out.println("Service is performing...");
}
}
```java
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyService(myRepository());
}
@Bean
public MyRepository myRepository() {
return new MyRepository();
}
}
```java
//模仿一个AnnotationConfigApplicationContext
private Map<String, Object> beanMap = new HashMap<>();
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
// 扫描并注册 Bean
for (Class<?> configClass : annotatedClasses) {
registerBeanDefinitions(configClass);
}
// 实例化所有 Bean
for (String beanName : beanDefinitionMap.keySet()) {
createBean(beanName);
}
}
private void registerBeanDefinitions(Class<?> configClass) {
if (configClass.isAnnotationPresent(Configuration.class)) {
for (Method method : configClass.getDeclaredMethods()) {
if (method.isAnnotationPresent(Bean.class)) {
String beanName = method.getName();
beanDefinitionMap.put(beanName, new BeanDefinition(configClass, method));
}
}
}
// 组件扫描(简化处理)
for (Class<?> clazz : configClass.getDeclaredClasses()) {
if (clazz.isAnnotationPresent(Component.class)) {
String beanName = decapitalize(clazz.getSimpleName());
beanDefinitionMap.put(beanName, new BeanDefinition(clazz));
}
}
}
private void createBean(String beanName) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getFactoryMethod() != null) {
try {
Object bean = beanDefinition.getFactoryMethod().invoke(beanDefinition.getBeanClass().newInstance());
beanMap.put(beanName, bean);
} catch (Exception e) {
throw new RuntimeException("Failed to create bean", e);
}
} else {
try {
Object bean = beanDefinition.getBeanClass().newInstance();
beanMap.put(beanName, bean);
} catch (Exception e) {
throw new RuntimeException("Failed to create bean", e);
}
}
}
public <T> T getBean(Class<T> requiredType) {
return requiredType.cast(beanMap.values().stream()
.filter(bean -> requiredType.isInstance(bean))
.findFirst()
.orElseThrow(() -> new RuntimeException("No bean found")));
}
private String decapitalize(String str) {
if (str == null || str.isEmpty()) {
return str;
}
return str.substring(0, 1).toLowerCase() + str.substring(1);
}
完成对beanfactory学习,下面我们来了解一下ApplicationContext:
ApplicationContext
继承自 BeanFactory
,并在此基础上扩展了大量功能以下是 ApplicationContext
提供的核心功能:
继承 BeanFactory
:ApplicationContext
继承了 BeanFactory
,因此具备了所有的 Bean 管理功能,如 Bean 的加载、实例化、依赖注入等。
事件机制:提供了发布和监听事件的能力(通过 ApplicationEvent
和 ApplicationListener
)。
国际化支持:通过 MessageSource
接口提供国际化消息的解析功能。
资源加载:通过 ResourceLoader
提供加载外部资源(如文件、URL)的功能。
自动装配:支持基于注解的自动装配(如 @Autowired
)。
环境管理:通过 Environment
接口管理环境变量和属性文件。
主要的实现类包括:
ClassPathXmlApplicationContext
:从类路径加载 XML 配置文件。
FileSystemXmlApplicationContext
:从文件系统加载 XML 配置文件。
AnnotationConfigApplicationContext
:基于 Java 配置类和注解的方式加载配置
选择在springboot启动类使用的AnnotationConfigApplicationContext来学习一下,下面是他的类图:
ApplicationContext
的初始化过程可以分为以下几个步骤:
- 创建
ApplicationContext
实例:通常由具体实现类如ClassPathXmlApplicationContext
或AnnotationConfigApplicationContext
来创建。 - 加载配置文件或配置类:解析配置文件(如 XML)或配置类(如 Java 类),生成
BeanDefinition
。 - 注册
BeanFactoryPostProcessor
:在加载完BeanDefinition
后,Spring 会注册并执行BeanFactoryPostProcessor
,允许在 Bean 实例化之前对BeanDefinition
进行修改。 - 初始化单例 Bean:在容器刷新时,会调用
preInstantiateSingletons()
方法,初始化所有非懒加载的单例 Bean。 - 注册
ApplicationListener
:在ApplicationContext
启动过程中,会注册所有的事件监听器,并且在事件发布时通知相应的监听器。 - 发布
ContextRefreshedEvent
事件:容器启动完毕后,会发布ContextRefreshedEvent
事件,所有监听器会收到通知。
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 准备上下文环境
prepareRefresh();
// 2. 初始化 BeanFactory 并加载 Bean 定义
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 对 BeanFactory 进行定制化,例如添加 BeanPostProcessor
prepareBeanFactory(beanFactory);
try {
// 4. 子类扩展点,留给子类实现,用于在 BeanFactory 标准初始化之后,进行定制化的扩展。
postProcessBeanFactory(beanFactory);
// 5. 执行 BeanFactoryPostProcessor,
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册 BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// 7. 初始化消息源(国际化功能)
initMessageSource();
// 8. 初始化事件机制
initApplicationEventMulticaster();
// 9. 子类扩展点:用于特殊 Bean 的初始化,提供给子类实现的扩展点,允许在刷新上下文时执行自定义逻辑。
onRefresh();
// 10. 注册监听器
registerListeners();
// 11. 初始化所有非懒加载的单例 Bean
finishBeanFactoryInitialization(beanFactory);
// 12. 完成刷新,发布事件
finishRefresh();
}
catch (BeansException ex) {
// 若出错,销毁已创建的单例 Bean
destroyBeans();
cancelRefresh(ex);
throw ex;
}
}
}
}
```java
/**
启动时间:记录容器的启动时间,以支持生命周期相关的功能。
环境验证:调用 getEnvironment().validateRequiredProperties() 方法,验证必要的环境属性是否存在。
事件机制准备:初始化早期的事件监听器和事件集合。
**/
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (this.logger.isInfoEnabled()) {
this.logger.info("Refreshing " + this);
}
// 初始化上下文环境属性
initPropertySources();
// 校验必要的属性
getEnvironment().validateRequiredProperties();
// 初始化 earlyApplicationListeners、earlyApplicationEvents 等
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
this.earlyApplicationEvents = new LinkedHashSet<>();
}
```java
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 关闭之前的 BeanFactory(如果有)
refreshBeanFactory();
// 获取新的 BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
return beanFactory;
}
```java
/**
设置类加载器:为 BeanFactory 设置类加载器,确保能够正确加载 Bean 类。
表达式解析:配置 BeanExpressionResolver,支持表达式语言(如 SpEL)的解析。
注册 BeanPostProcessor:注册一个 ApplicationContextAwareProcessor,用于在 Bean 实例化后进行自定义处理。
忽略依赖接口:忽略一些特殊的依赖接口,这些接口会在 Bean 初始化时自动注入。
注册默认依赖:如 Environment 和 BeanFactory,这些依赖将自动注入到需要的 Bean 中。
**/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置类加载器
beanFactory.setBeanClassLoader(getClassLoader());
// 设置表达式语言处理器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 添加 PropertyEditor 支持
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 添加 BeanPostProcessor
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 忽略一些依赖接口
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// 注册一些默认的依赖,如 Environment
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
}
```java
protected void finishRefresh() {
// 清除上下文缓存
clearResourceCaches();
// 初始化生命周期管理器
initLifecycleProcessor();
// 启动所有的生命周期 Bean
getLifecycleProcessor().onRefresh();
// 发布容器刷新完成事件
publishEvent(new ContextRefreshedEvent(this));
// 注册JMX相关的内容(可选)
LiveBeansView.registerApplicationContext(this);
}
设计中使用了多种设计模式:
工厂模式(Factory Pattern):
ApplicationContext
通过工厂模式来创建和管理 Bean 对象。模板方法模式(Template Method Pattern):
AbstractApplicationContext
中定义了refresh()
方法,具体实现类可以在这个模板方法中定制容器的启动过程。观察者模式(Observer Pattern):通过事件机制,实现了监听器对事件的观察与响应。
策略模式(Strategy Pattern):
BeanPostProcessor
和BeanFactoryPostProcessor
的实现允许用户自定义 Bean 的创建和初始化逻辑。
ApplicationContext` 的设计遵循了一些重要的面向对象设计原则:
- 单一职责原则 (SRP):
ApplicationContext
本身不直接管理 Bean,而是通过BeanFactory
来实现,这样确保了每个类只承担一个职责。 - 开放-封闭原则 (OCP):
ApplicationContext
提供了多种扩展点,如BeanPostProcessor
、BeanFactoryPostProcessor
、ApplicationListener
,允许用户在不修改框架代码的情况下,定制容器的行为。 - 依赖倒置原则 (DIP):高层次的
ApplicationContext
依赖于抽象的BeanFactory
,而不是具体的实现类,这使得ApplicationContext
可以灵活地支持不同类型的 Bean 管理方式。
BeanPostProcessor 和 BeanFactoryPostProcessor
BeanPostProcessor
接口允许在 Bean 实例化之后、初始化之前和之后对 Bean 进行修改。它的典型用途包括:
- 设置代理对象。
- 修改属性值。
- 检查特定条件
核心方法:
postProcessBeforeInitialization(Object bean, String beanName)
: 在 Bean 初始化之前调用。postProcessAfterInitialization(Object bean, String beanName)
: 在 Bean 初始化之后调用。
BeanFactoryPostProcessor
接口允许在容器加载 Bean 定义后但在实例化 Bean 之前,对 BeanDefinition 进行修改。可以用来动态修改 Bean 配置。
核心方法:
postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
: 允许对 BeanFactory 的配置进行定制。
一些常用的beanPostprocessor :
CommonAnnotationBeanPostProcessor
- 处理 Java EE 标准中的注解:
@PostConstruct
、@PreDestroy
、@Resource
- 确保这些注解在 Spring 管理的 Bean 上正确执行
AutowiredAnnotationBeanPostProcessor
- 处理
@Autowired
、@Value
和@Inject
注解 - 实现依赖注入的核心,自动注入依赖或外部化配置
RequiredAnnotationBeanPostProcessor
- 处理
@Required
注解 - 确保在 Bean 初始化时,所有使用
@Required
标注的属性都已被设置
InstantiationAwareBeanPostProcessor
- 扩展了
BeanPostProcessor
的功能 - 允许在 Bean 实例化之前进行操作,以及在属性注入阶段进行干预
ApplicationContextAwareProcessor
- 处理实现了
ApplicationContextAware
接口的 Bean - 确保在 Bean 初始化过程中注入 Spring 容器的上下文(
ApplicationContext
)
AspectJAwareAdvisorAutoProxyCreator
- 用于 AOP 的实现,自动代理所有基于 AspectJ 的切面
- 检查是否需要为当前 Bean 创建代理对象,应用相关通知器(Advisor)
InitDestroyAnnotationBeanPostProcessor
- 处理自定义的初始化和销毁方法
- 允许使用自定义注解指定 Bean 初始化后和销毁前需要执行的特定方法
PersistenceAnnotationBeanPostProcessor
- 处理 JPA 中的
@PersistenceContext
和@PersistenceUnit
注解 - 自动注入
EntityManager
和EntityManagerFactory
,用于数据库操作
ScheduledAnnotationBeanPostProcessor
- 处理
@Scheduled
注解,用于定时任务的执行 - 注册定时任务并由 Spring 的任务调度器管理
ConfigurationClassPostProcessor
处理 @Configuration
注解:ConfigurationClassPostProcessor
会扫描并解析标注了 @Configuration
的类,将其作为配置类来处理。这些配置类通常用来定义 @Bean
方法,并可以包括其他注解如 @ComponentScan
和 @Import
。
解析 @Bean
方法:在解析 @Configuration
类时,ConfigurationClassPostProcessor
会识别并处理 @Bean
注解的方法,将这些方法返回的对象作为 Spring 容器中的 Bean 进行注册。
代理增强:对于标注了 @Configuration
的类,Spring 可能会对其生成 CGLIB 代理,以确保 @Bean
方法之间的调用能正确处理单例模式。
ImportAwareBeanPostProcessor
处理 @Import
注解:ImportAwareBeanPostProcessor
处理那些实现了 ImportAware
接口的类,使它们能够感知它们是通过 @Import
注解被引入的,以及引入它们的配置类。
环境感知:通过 ImportAware
接口,配置类可以获取到引入它们的其他配置类的信息,这有助于动态调整配置或逻辑。
@Component
class MyBean implements InitializingBean, DisposableBean {
private String message;
public MyBean() {
System.out.println("Bean实例化");
}
public void setMessage(String message) {
this.message = message;
System.out.println("属性设置:" + message);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化方法:调用 afterPropertiesSet()");
}
public void customInit() {
System.out.println("自定义初始化方法:customInit()");
}
public void sayHello() {
System.out.println("Hello from MyBean: " + message);
}
@Override
public void destroy() throws Exception {
System.out.println("销毁方法:调用 destroy()");
}
public void customDestroy() {
System.out.println("自定义销毁方法:customDestroy()");
}
}
```java
class MyApplicationListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
// 在应用程序上下文刷新时执行的逻辑
System.out.println("Application context has been refreshed!!!"+event.getEventData());
}
}
class MyEvent extends ApplicationEvent {
private String eventData;
public MyEvent(Object source, String eventData) {
super(source);
this.eventData = eventData;
}
public String getEventData() {
return eventData;
}
}
```java
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("ryu",MyBean.class,() -> new MyBean());
BeanFactoryPostProcessor beanFactoryPostProcessor = new BeanFactoryPostProcessor() {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryPostProcessor");
MyBean bean = (MyBean) beanFactory.getBean("ryu");
bean.sayHello();
}
};
DefaultListableBeanFactory defaultListableBeanFactory = context.getDefaultListableBeanFactory();
defaultListableBeanFactory.addBeanPostProcessor(new BeanPostProcessor() {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean.getClass()==MyBean.class){
System.out.println("之前:"+"BeanPostProcessor");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean.getClass()==MyBean.class){
System.out.println("之后:"+"BeanPostProcessor");
}
return bean;
}
});
context.addBeanFactoryPostProcessor(beanFactoryPostProcessor);
context.setApplicationStartup(ApplicationStartup.DEFAULT);
context.addApplicationListener(new MyApplicationListener());
context.refresh();
context.publishEvent(new MyEvent(this, "CustomEventData"));
MyBean bean = context.getBean(MyBean.class);
MyBean bean2 = context.getBean(MyBean.class);
System.out.println(bean == bean2);
context.close();
Spring 容器的启动流程
配置解析:Spring 解析配置文件(如 XML 或 Java 配置类),并读取所有的
BeanDefinition
。BeanDefinition 注册:将解析得到的
BeanDefinition
注册到容器中。BeanDefinition
是对 Bean 的描述信息,包括类名、作用域、依赖等。Bean 初始化
:
单例模式:
ApplicationContext
会在启动时创建所有的单例 Bean 实例。原型模式:每次请求时才会创建新的 Bean 实例。
依赖注入:Spring 使用构造函数注入、setter 注入或注解注入,将依赖的 Bean 注入到目标对象中。
后处理器调用:如果注册了
BeanPostProcessor
或BeanFactoryPostProcessor
,Spring 会在 Bean 实例化之前和之后调用这些后处理器,以便进行自定义逻辑处理。Bean 就绪:所有 Bean 都完成初始化和依赖注入后,Spring 容器准备就绪,可以接收请求或执行应用逻辑。
Bean 的生命周期
1. Bean 实例化
- 过程:Spring 根据配置(例如 XML 配置、注解、Java 配置类等)实例化 Bean。这个阶段通过调用 Bean 的构造函数创建 Bean 对象。
- 相关接口:
BeanFactory
或ApplicationContext
会调用 Bean 的构造函数来创建实例。
2. 属性填充
- 过程:在实例化之后,Spring 会注入 Bean 的依赖项。这包括通过构造函数注入、setter 方法注入或字段注入的方式来设置 Bean 的属性。
- 相关注解:
@Autowired
、@Value
等。
3. 初始化
- 过程:在所有依赖项注入完成后,Spring 会执行 Bean 的初始化过程。如果 Bean 实现了
InitializingBean
接口,则会调用afterPropertiesSet()
方法。此外,还可以通过@PostConstruct
注解指定初始化方法。 - 相关接口/注解:
InitializingBean
、@PostConstruct
、init-method
(在 XML 配置中)。
4. 使用
- 过程:Bean 现在已经完全初始化,可以被应用程序使用。此阶段 Bean 处于活动状态,可以处理业务逻辑。
5. 销毁
过程:当 Spring 容器关闭或 Bean 不再需要时,Bean 会被销毁。在销毁之前,Spring 会执行清理操作。如果 Bean 实现了
DisposableBean
接口,则会调用destroy()
方法。此外,可以通过@PreDestroy
注解指定销毁方法。相关接口/注解:
DisposableBean
、@PreDestroy
、destroy-method
(在 XML 配置中)。Bean的循环依赖
循环依赖发生在两个或多个 Bean 之间存在相互依赖的情况。例如,Bean A 依赖于 Bean B,同时 Bean B 也依赖于 Bean A。Spring 需要解决这种情况,以确保 Bean 的正确创建和依赖注入。
构造函数注入的循环依赖
- 问题:构造函数注入的循环依赖无法处理,因为 Spring 无法在 Bean 的构造函数中创建出完整的实例。在 Bean A 的构造函数中需要 Bean B,而 Bean B 的构造函数中又需要 Bean A,这种情况会导致死锁或错误。
- 解决方案:通常推荐避免使用构造函数注入来处理循环依赖。可以使用 setter 注入或字段注入来替代,这样 Spring 可以在实例化 Bean 后再注入依赖项,从而解决循环依赖问题。
Setter 注入的循环依赖
Spring 能够处理 setter 注入的循环依赖,利用三级缓存机制来解决这个问题。具体的机制如下:
三级缓存机制
一级缓存(
singletonObjects
)内容:存储完全初始化好的 Bean 实例。Bean 在完全创建并完成依赖注入后会被放入这里。
作用:提供对完全初始化的 Bean 的访问。
二级缓存(
earlySingletonObjects
)内容:存储尚未完成初始化但已被实例化的 Bean。这些 Bean 的实例化完成,但可能还没有完全注入依赖项。
作用:允许在依赖注入过程中解决循环依赖。由于 Bean 尚未完成初始化,Spring 可以提供部分创建的 Bean 实例给其他 Bean 的注入过程。
三级缓存(
singletonFactories
)内容:存储
ObjectFactory
实例,这些实例负责创建 Bean 实例。这里存储的是用来创建 Bean 的工厂对象,而不是实际的 Bean 实例。作用:允许 Spring 在 Bean 的实例化过程中将其注册到缓存中,从而处理依赖注入。
解决循环依赖的流程:
创建 Bean A 和 Bean B 的
ObjectFactory
三级缓存 (
singletonFactories
):
- Spring 为 Bean A 和 Bean B 分别创建
ObjectFactory
对象。这些ObjectFactory
对象负责延迟创建 Bean 实例,直到其所有依赖项都准备好。 - 这些
ObjectFactory
对象被放置在三级缓存中,等待完成依赖注入后再创建 Bean 实例。
- Spring 为 Bean A 和 Bean B 分别创建
部分创建的 Bean 存储在二级缓存中
二级缓存 (
earlySingletonObjects
):
- Spring 将尚未完全初始化的 Bean 实例(即 Bean B)存储在二级缓存中。这时 Bean B 已经创建,但尚未完成所有的依赖注入。
- 当 Bean A 需要 Bean B 时,Spring 从二级缓存中获取 Bean B 的部分创建实例。
解决循环依赖
Bean A 的实例
:
- Bean A 依赖于 Bean B。由于 Bean B 已经被部分创建并存储在二级缓存中,Spring 可以将 Bean B 的部分实例注入到 Bean A 中。
Bean B 的实例
:
- Bean B 依赖于 Bean A。Spring 将 Bean A 的
ObjectFactory
放入三级缓存中,以便在 Bean A 完全初始化后创建 Bean A 的实例,并完成 Bean B 的初始化。
- Bean B 依赖于 Bean A。Spring 将 Bean A 的
完成 Bean 的初始化
完成 Bean A 和 Bean B 的初始化
:
- 一旦 Bean A 和 Bean B 的所有依赖注入和初始化操作完成后,它们会被移到一级缓存 (
singletonObjects
) 中。 - Bean A 和 Bean B 的实例现在都完全初始化,并且可以正常使用。
- 一旦 Bean A 和 Bean B 的所有依赖注入和初始化操作完成后,它们会被移到一级缓存 (