Spring源码分析之预启动流程

简介: Spring源码分析之预启动流程

在应用程序中,一般是通过创建ClassPathXmlApplicationContextAnnotationConfigApplicationContext这两个最底层子类来启动Spring IOC容器:

  • ClassPathXmlApplicationContext: xml文件配置版
  • AnnotationConfigApplicationContext: 注解版

由于当下越来越流行基于Java注解的配置来创建我们的Bean,所以本文主要以注解版进行探析。

AnnotationConfigApplicationContext的类关系结构

我们先来看看我们探讨的起点

public class Main {
  public static void main(String[] args) {
    new AnnotationConfigApplicationContext(Config.class);
  }
  @Configuration
  public static class Config{
  }
}

demo简简单单,那么,这里发生了什么?或许,我们可以先看看AnnotationConfigApplicationContext的类关系结构:

AnnotationConfigApplicationContext的类关系结构.png

我们可以看到AnnotationConfigApplicationContext最上面有两个顶级接口:

  • BeanFactory: Spring的核心接口,纯粹的bean容器,主要定义了与Bean的相关方法
  • ResourceLoader:资源加载器,定义了getResource方法

继承自三个父类:

  • DefaultResourceLoader: 默认的资源加载器,实现了三种加载资源的方式
  1. 通过path加载资源
  2. 通过classpath加载资源
  3. 通过URL加载资源
  • AbstractApplicationContext: 实现了ApplicationContext接口的抽象类,主要功能
  1. 实现了启动IOC容器的核心方法:refresh()
  2. 发布事件
  3. 大量getBean相关的操作, 主要通过抽象方法getBeanFactory基于子类实现
  4. 大量留于子类扩展的空方法
  5. 消息国际化
  • GenericApplicationContext:
  1. 使用组合的方式引进了最底层的BeanFactory实现类:DefaultListableBeanFactory
  2. 定义了registerBean的相关操作,其实是通过DefaultListableBeanFactory实现的

不难发现,ApplicationContext名副其实,确实就是一个应用上下文,对于bean的相关操作,容器的管理,依旧是由我们的BeanFactory进行实现。

准备启动

1. 创建我们的实例:AnnotationConfigApplicationContext

new AnnotationConfigApplicationContext(Config.class);

2.进入到AnnotationConfigApplicationContext构造方法

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this();
    register(annotatedClasses);
    refresh();
}

3. 调用我们的空构造方法,这里要先实例化我们的父类

3.1 实例化DefaultResourceLoader

public DefaultResourceLoader() {
  this.classLoader = ClassUtils.getDefaultClassLoader();
}

ClassUtils.getDefaultClassLoader()主要有两步操作

//获取线程上下文的类加载器
ClassLoader cl = = Thread.currentThread().getContextClassLoader();
if(cl == null) //为空则获取系统的类加载器 即为应用类加载器
    cl = ClassLoader.getSystemClassLoader();

这里我们非Tomcat环境,所以返回的是AppClassLoader

3.2 实例化AbstractApplicationContext

//为BeanFactoryPostProcessor赋初始值
List<BeanFactoryPostProcessor> BeanFactoryPostProcessor = new ArrayList<>();
public AbstractApplicationContext() {
    //引入一个资源解析器
    this.resourcePatternResolver = getResourcePatternResolver();
}
protected ResourcePatternResolver getResourcePatternResolver() {
    return new PathMatchingResourcePatternResolver(this);
}

3.3 实例化GenericApplicationContext

public GenericApplicationContext() {
    //引入BeanFactory实现
    this.beanFactory = new DefaultListableBeanFactory();
}

3.4 实例化自己

public AnnotationConfigApplicationContext() {
    //初始化基于注解的bean定义扫描器
    this.reader = new AnnotatedBeanDefinitionReader(this);
    //初始化基于classpath的bean定义扫描器
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}
3.4.1 AnnotatedBeanDefinitionReader初始化过程
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    this(registry, getOrCreateEnvironment(registry));
}
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    //registry就是我们AnnotationConfigApplicationContext
    this.registry = registry;
    //引入条件表达式计算器 处理@Conditional注解
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    //注册所有与注解相关的后置处理器
  AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
  registerAnnotationConfigProcessors(registry, null);
}

registerAnnotationConfigProcessors(registry, null)中主要做了以下几件事情:

  • DefaultListableBeanFactory赋值了两个引用
//依赖排序器,用于处理添加了Priority、Order注解以及实现了Ordered接口的bean
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
//@Autowire候选解析器
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
  • 往容器中注册了6个后置处理器的bean定义
    注册配置类的后置处理器
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME);
  • 注册处理@Autowired注解的后置处理器
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME);
  • 注册处理@Required注解的后置处理器(5.1版本开始已被废弃)
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME);
  • 注册处理JSR-250规范注解的后置处理器,@Resource,@PostConstruct,@PreDestroy
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME);
  • 注册处理@EventListener注解的后置处理器
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME);
  • 注册事件监听工厂,给上面的EventListenerMethodProcessors使用
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME);
3.4.2 ClassPathBeanDefinitionScanner初始化过程

经历了一系列的构造器传递

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
    this(registry, true);
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
    this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
                                      Environment environment) {
    this(registry, useDefaultFilters, environment,
         (registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
}

最终实现的构造器方法

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
                                      Environment environment, @Nullable ResourceLoader resourceLoader) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    this.registry = registry;
  //默认为true
    if (useDefaultFilters) {
        //注册默认的过滤器
        registerDefaultFilters();
    }
    //设置环境
    setEnvironment(environment);
    //设置资源加载器
    setResourceLoader(resourceLoader);
}

registerDefaultFilters方法

protected void registerDefaultFilters() {
    //加入扫描@Component注解的过滤器,这样就能扫到@Controller,@Service...
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
    try {
        //JSR-250规范的注解
        this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
    }
    catch (ClassNotFoundException ex) {
    }
    try {
        //JSR-330规范的注解
        this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
    }
    catch (ClassNotFoundException ex) {
    }
}

4. 构造方法执行完毕,执行register(annotatedClasses)方法,将配置类的bean定义注册到容器中

public void register(Class<?>... annotatedClasses) {
    Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
    //这里就使用了刚刚初始化的AnnotatedBeanDefinitionReader扫码器
    //annotatedClasses即为在入口处传进的自定义配置类Config.class
    this.reader.register(annotatedClasses);
}
public void register(Class<?>... annotatedClasses) {
    for (Class<?> annotatedClass : annotatedClasses) {
        //这里我们只传了一个,只有一次循环
        registerBean(annotatedClass);
    }
}
public void registerBean(Class<?> annotatedClass) {
    //spring的特点,真正实现的都是do开头的方法
    doRegisterBean(annotatedClass, null, null, null);
}
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
                        @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
    //将class封装到bean定义中
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
    //由于配置类并未使用@Conditional注解,直接返回false
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }
    abd.setInstanceSupplier(instanceSupplier);
    //解析bean定义的作用域
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    //处理普通的bean定义注解,@Lazy @Primary @DependsOn @Role @Description
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    if (qualifiers != null) {
        for (Class<? extends Annotation> qualifier : qualifiers) {
            if (Primary.class == qualifier) {
                abd.setPrimary(true);
            }
            else if (Lazy.class == qualifier) {
                abd.setLazyInit(true);
            }
            else {
                abd.addQualifier(new AutowireCandidateQualifier(qualifier));
            }
        }
    }
    for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
        customizer.customize(abd);
    }
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    //根据scopeMetadata中的proxy-mode属性判断是否需要进行代理封装,默认否
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    //将bean定义注册到容器中
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
} 

前期准备工作已基本完毕,可以开始调用refresh方法启动IOC容器了。

目录
相关文章
|
7天前
|
监控 Java 应用服务中间件
Spring Boot整合Tomcat底层源码分析
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置和起步依赖等特性,大大简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是其与Tomcat的整合。
26 1
|
23天前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
31 1
|
24天前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
25 1
|
1月前
|
缓存 JavaScript Java
Spring之FactoryBean的处理底层源码分析
本文介绍了Spring框架中FactoryBean的重要作用及其使用方法。通过一个简单的示例展示了如何通过FactoryBean返回一个User对象,并解释了在调用`getBean()`方法时,传入名称前添加`&`符号会改变返回对象类型的原因。进一步深入源码分析,详细说明了`getBean()`方法内部对FactoryBean的处理逻辑,解释了为何添加`&`符号会导致不同的行为。最后,通过具体代码片段展示了这一过程的关键步骤。
Spring之FactoryBean的处理底层源码分析
|
2月前
|
缓存 安全 Java
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
从底层源码入手,通过代码示例,追踪AnnotationConfigApplicationContext加载配置类、启动Spring容器的整个流程,并对IOC、BeanDefinition、PostProcesser等相关概念进行解释
214 24
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
|
20天前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
22 0
|
1月前
|
XML Java 应用服务中间件
【Spring】运行Spring Boot项目,请求响应流程分析以及404和500报错
【Spring】运行Spring Boot项目,请求响应流程分析以及404和500报错
179 2
|
1月前
|
JSON 前端开发 JavaScript
优雅!Spring Boot 3.3 实现职责链模式,轻松应对电商订单流程
本文介绍如何使用 Spring Boot 3.3 实现职责链模式,优化电商订单处理流程。通过将订单处理的各个环节(如库存校验、优惠券核验、支付处理等)封装为独立的处理器,并通过职责链将这些处理器串联起来,实现了代码的解耦和灵活扩展。具体实现包括订单请求类 `OrderRequest`、抽象处理器类 `OrderHandler`、具体处理器实现(如 `OrderValidationHandler`、`VerifyCouponHandler` 等)、以及初始化职责链的配置类 `OrderChainConfig`。
|
4月前
|
Java 持续交付 Maven
Spring Boot程序的打包与运行:构建高效部署流程
构建高效的Spring Boot部署流程对于保障应用的快速、稳定上线至关重要。通过采用上述策略,您可以确保部署过程的自动化、可靠性和高效性,从而将专注点放在开发上面。无论是通过Maven的生命周期命令进行打包,还是通过容器技术对部署过程进行优化,选择正确的工具与实践是成功实现这一目标的关键。
200 2
|
5月前
|
存储 安全 Java
Spring Security 6.x OAuth2登录认证源码分析
上一篇介绍了Spring Security框架中身份认证的架构设计,本篇就OAuth2客户端登录认证的实现源码做一些分析。
233 2
Spring Security 6.x OAuth2登录认证源码分析
下一篇
无影云桌面