Spring Framework 启动流程分析

Spring Framework 是一个功能强大且灵活的用于构建企业级 Java 应用程序的框架。理解 Spring Framework 的启动流程对于深入掌握其工作机制、调试应用程序以及进行高级定制非常重要。本文将详细介绍 Spring Framework 的启动流程,并结合关键源码类和方法进行说明。

应用程序的入口点

在 Spring Framework 中,应用程序的启动通常涉及创建和配置一个 ApplicationContext。常见的方式包括使用 ClassPathXmlApplicationContextAnnotationConfigApplicationContext 或通过 ContextLoader 在 Web 应用中加载上下文。

以下是使用 AnnotationConfigApplicationContext 启动一个简单 Spring 应用的示例:

1
2
3
4
5
6
7
8
public class MyApp {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyBean myBean = context.getBean(MyBean.class);
myBean.doSomething();
context.close();
}
}

关键源码

  • AnnotationConfigApplicationContext

    该类是基于 Java 配置的 ApplicationContext 实现。它主要负责扫描和注册基于注解的配置类和组件。

    1
    2
    3
    public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
    // 构造函数和方法
    }

创建 ApplicationContext 实例

AnnotationConfigApplicationContext 为例,其构造函数会执行以下步骤:

1
2
3
4
5
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}

关键步骤解析

  1. 注册配置类

    register 方法将传入的配置类注册到上下文中。

    1
    2
    3
    4
    5
    @Override
    public void register(Class<?>... componentClasses) {
    Assert.notEmpty(componentClasses, "At least one component class must be specified");
    this.reader.loadBeanDefinitions(new AnnotatedBeanDefinitionReader(this).register(componentClasses).getRegistry());
    }
  2. 刷新上下文

    refresh 方法是 AbstractApplicationContext 中的重要方法,负责初始化上下文,包括加载 Bean 定义、初始化 BeanFactory、触发生命周期回调等。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    @Override
    public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
    // 准备此上下文进行刷新
    prepareRefresh();
    // 告诉子类刷新内部Bean工厂
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    // 准备Bean工厂以供此上下文使用
    prepareBeanFactory(beanFactory);
    try {
    // 允许在上下文子类中对Bean工厂进行后处理
    postProcessBeanFactory(beanFactory);
    // 调用注册为上下文中的Bean的工厂处理器
    invokeBeanFactoryPostProcessors(beanFactory);
    // 注册拦截Bean创建的Bean处理器
    registerBeanPostProcessors(beanFactory);
    // 初始化此上下文的消息源
    initMessageSource();
    // 初始化此上下文的事件多播器
    initApplicationEventMulticaster();
    // 在特定的上下文子类中初始化其他特殊Bean
    onRefresh();
    // 检查监听器Bean并注册它们
    registerListeners();
    // 实例化所有剩余的(非延迟初始化)单例
    finishBeanFactoryInitialization(beanFactory);
    // 最后一步:发布相应的事件
    finishRefresh();
    } catch (BeansException ex) {
    ...
    } finally {
    // 重置Spring核心中的公共缓存,因为我们可能不再需要单例Bean的元数据了...
    resetCommonCaches();
    }
    }
    }

准备刷新上下文

prepareRefresh 方法执行一些准备工作,如设置启动标志、初始化 EnvironmentPropertySources 等。

1
2
3
4
5
6
7
8
9
10
protected void prepareRefresh() {
// 设置启动标志
this.startupDate = System.currentTimeMillis();
this.closed.set(false);

// 初始化 Environment
initPropertySources();

// 其他准备工作
}

获取和配置 BeanFactory

obtainFreshBeanFactory 方法负责创建或获取一个全新的 BeanFactory 实例,并加载 Bean 定义。

1
2
3
4
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
  • refreshBeanFactory 方法

    GenericApplicationContext 中,该方法通常会创建一个 DefaultListableBeanFactory 并加载 Bean 定义。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    protected void refreshBeanFactory() throws BeansException, IllegalStateException {
    if (this.beanFactory != null) {
    destroyBeans();
    closeBeanFactory();
    }
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(getInternalParentBeanFactory());
    beanFactory.setSerializationId(getId());

    // 加载 Bean 定义
    loadBeanDefinitions(beanFactory);
    this.beanFactory = beanFactory;
    }

准备 BeanFactory

prepareBeanFactory 方法对 BeanFactory 进行一些通用的设置,如设置类加载器,设置默认忽略依赖类型,注册早先的 BeanPostProcessors等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置类加载器
beanFactory.setBeanClassLoader(getClassLoader());

// 添加默认的忽略依赖类型
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

// 注册默认的 BeanPostProcessor
if (!beanFactory.containsBean(IGNORE_DEPENDENCY_ANNOTATION_PROCESSOR_BEAN_NAME)) {
beanFactory.registerBeanDefinition(IGNORE_DEPENDENCY_ANNOTATION_PROCESSOR_BEAN_NAME,
new RootBeanDefinition(AnnotationAwareOrderComparator.class));
}

// 其他设置
}

关键设置

  • 类加载器:确保 BeanFactory 使用正确的类加载器。
  • 忽略依赖接口:注册一些特殊接口,如 EnvironmentAwareApplicationContextAware 等,使 BeanFactory 在自动装配时忽略这些接口。
  • ApplicationListenerDetector:注册早期后处理器,用于将内部 bean 检测为 ApplicationListeners。

应用 BeanFactory 后处理器

invokeBeanFactoryPostProcessors 方法执行所有注册的 BeanFactoryPostProcessor,如 PropertyPlaceholderConfigurerConfigurationClassPostProcessor 等。

1
2
3
4
5
6
7
8
9
void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 获取所有 BeanFactoryPostProcessor
Map<String, BeanFactoryPostProcessor> postProcessors = beanFactory.getBeansOfType(BeanFactoryPostProcessor.class, true, false);

// 执行所有 BeanFactoryPostProcessor
for (BeanFactoryPostProcessor processor : postProcessors.values()) {
processor.postProcessBeanFactory(beanFactory);
}
}

关键 Post-Processors

  • **ConfigurationClassPostProcessor**:解析 @Configuration 类,处理注解如 @Bean@ComponentScan 等,注册相应的 Bean 定义。

    1
    2
    3
    4
    5
    6
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    // 解析配置类
    SourceClass sourceClass = new SourceClass(configurationClass);
    // 处理 @Bean、@ComponentScan 等注解
    }
  • **PropertySourcesPlaceholderConfigurer**:解析 @Value 注解中的占位符,并替换为实际的属性值。

注册 BeanPostProcessors

registerBeanPostProcessors 方法负责注册所有的 BeanPostProcessor,如 AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor 等。

1
2
3
4
5
6
7
8
9
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 获取所有 BeanPostProcessor
Map<String, BeanPostProcessor> postProcessors = beanFactory.getBeansOfType(BeanPostProcessor.class, true, false);

// 注册到 BeanFactory
for (BeanPostProcessor processor : postProcessors.values()) {
beanFactory.addBeanPostProcessor(processor);
}
}

关键 BeanPostProcessors

  • **AutowiredAnnotationBeanPostProcessor**:处理 @Autowired@Value 注解,实现自动装配。
  • **CommonAnnotationBeanPostProcessor**:处理 JSR-250 注解,如 @PostConstruct@PreDestroy 等。
  • **RequiredAnnotationBeanPostProcessor**:处理 @Required 注解,确保依赖项被正确注入。

初始化 MessageSource

如果应用程序需要国际化支持,initializeMessageSource 方法会初始化 MessageSource

1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected void initializeMessageSource() {
if (getBeanFactory().containsBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = getBeanFactory().getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
((HierarchicalMessageSource) this.messageSource).setParentMessageSource(this.parent.getMessageSource());
}
}
else {
DelegatingMessageSource messageSource = new DelegatingMessageSource();
messageSource.setParentMessageSource((this.parent != null ? this.parent.getMessageSource() : null));
this.messageSource = messageSource;
getBeanFactory().registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
}
}

完成 BeanFactory 初始化

finishBeanFactoryInitialization 方法完成 BeanFactory 的初始化,包括实例化所有非懒加载的单例 Bean。

1
2
3
4
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 设置忽略不存在的依赖(可选)
beanFactory.preInstantiateSingletons();
}

预实例化单例 Bean

preInstantiateSingletons 方法遍历所有的 Bean 定义,并实例化非懒加载的单例 Bean。

1
2
3
4
5
6
7
8
public void preInstantiateSingletons() throws BeansException {
// 遍历所有 Bean 定义
for (String beanName : this.beanDefinitionNames) {
if (!containsSingleton(beanName)) {
getBean(beanName);
}
}
}

完成刷新上下文

finishRefresh 方法执行一些收尾工作,如发布 ContextRefreshedEvent 事件、启动生命周期 Bean(如 Lifecycle 接口实现的 Bean)等。

1
2
3
4
5
6
7
8
9
10
protected void finishRefresh() {
// 初始化生命周期管理器
initLifecycleProcessor();

// 启动生命周期管理器
getLifecycleProcessor().start();

// 发布 ContextRefreshedEvent 事件
publishEvent(new ContextRefreshedEvent(this));
}

使用 ApplicationContext

一旦 ApplicationContext 完成初始化,应用程序就可以使用它来获取 Bean、发布事件等。

1
2
MyBean myBean = context.getBean(MyBean.class);
myBean.doSomething();

关闭上下文

在应用程序结束时,调用 close 方法关闭 ApplicationContext,触发销毁钩子和 DisposableBean 接口的回调。

1
context.close();

关键方法

1
2
3
4
5
6
7
8
9
10
11
public void close() {
synchronized (this.startupShutdownMonitor) {
// 发布 ContextClosedEvent 事件
publishEvent(new ContextClosedEvent(this));

// 销毁所有单例 Bean
getBeanFactory().destroySingletons();

// 其他销毁工作
}
}

总结

Spring Framework 的启动流程涉及多个关键步骤,每个步骤都通过多个类和方法协同工作,以确保应用程序的正确初始化和运行。以下是主要步骤和相关关键组件的总结:

  1. 创建 ApplicationContext:通过特定的 ApplicationContext 实现(如 AnnotationConfigApplicationContext)创建上下文实例。
  2. 注册配置类或 Bean 定义:使用注解或 XML 文件注册应用程序的 Bean 定义。
  3. 刷新上下文
    • 准备刷新:设置环境、初始化属性源等。
    • 获取和配置 BeanFactory:创建 BeanFactory 实例,设置类加载器、忽略接口等。
    • 应用 BeanFactoryPostProcessors:执行所有的 BeanFactoryPostProcessor,如 ConfigurationClassPostProcessor
    • 注册 BeanPostProcessors:注册所有的 BeanPostProcessor,如 AutowiredAnnotationBeanPostProcessor
    • 初始化 MessageSource:如果需要,初始化消息源用于国际化。
    • 完成 BeanFactory 初始化:预实例化所有非懒加载的单例 Bean。
    • 完成刷新:初始化生命周期管理器,发布 ContextRefreshedEvent 事件。
  4. 使用 ApplicationContext:获取和使用 Bean,发布事件等。
  5. 关闭上下文:在应用程序结束时,关闭上下文,触发销毁钩子和事件。

通过以上步骤,Spring Framework 能够高效地管理生命周期、依赖注入、Bean 的创建与销毁、事件发布等核心功能。理解这些流程和相关源码,对于深入掌握 Spring Framework 的工作机制、优化应用程序性能以及进行高级定制具有重要意义。