Spring Boot运行机制

        大家好,我是丁甲,很久没有写博客了,最近由于工作原因,需要重新面试,所以最近会写几篇关于面试的博客。

Spring Boot的运行机制是什么?

        这个问题通常会被问到,之前丁甲也只是背书应付面试,但这样始终是好的,于是我决定看看Spring  Boot注解的源码,并从源码层面上来看看Spring Boot的运行机制究竟是什么。

        首先,我们随便打开一个Spring Boot项目,我们能够发现他的启动类是都是有一个非常重要的注解:  

@SpringBootApplication
public class Demo123Application {

    public static void main(String[] args) {
        SpringApplication.run(Demo123Application.class, args);
    }

}

        这个非常重要的注解就是@SpringBootApplicaiton。

   

        其次,任意打开一个SpringBoot项目,不难发现他的启动类(使用@SpringBootApplication注解的类)目录层级非常高,是顶级目录,这是为什么呢?今天我们从源码的角度出发,进一步的解析SpringBoot项目的运行机制。

 

@SpringBootApplication注解是一个复合注解

        @SpringBootApplication是一个复合注解,并非一个单一的注解,我们点开一个@SpringBootApplication就不难发现:

  

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    Class<?>[] exclude() default {};

    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    String[] excludeName() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "nameGenerator"
    )
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

        从这段源码中不难看出,@SpringBootApplication注解是由多个注解组合而成的,而在这几个组合注解中其中最重要的核心注解当属@EnableAutoConfiguration、@ComponentScan、@Configuration。

        我们从这三个核心注解来分下SpringBoot项目的运行机制。

 

@Configuration注解

        源码:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";

    boolean proxyBeanMethods() default true;
}

        @coofiguration注解是一个十分常用的注解,经常都会用到。它的作用通过java类将写好的类在Spring容器初始化的时候将其加载到Spring容器中去,摒弃了xml配置文件来初始化Bean,十分的方便,和他一起使用的注解为@Bean

 

@ComponentScan

        源码:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
    @AliasFor("basePackages")
    String[] value() default {};

    @AliasFor("value")
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

    String resourcePattern() default "**/*.class";

    boolean useDefaultFilters() default true;

    ComponentScan.Filter[] includeFilters() default {};

    ComponentScan.Filter[] excludeFilters() default {};

    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;

        @AliasFor("classes")
        Class<?>[] value() default {};

        @AliasFor("value")
        Class<?>[] classes() default {};

        String[] pattern() default {};
    }
}

        @componentScan注解,是一个扫描包的注解。在Spring容器初始化的时候,invokeBeanFactoryPostProcessor()方法中会将所有的@componentScan下面的包扫描并将类通过一系列的操作(java  -> class ->BeanDefinitonMap ->Singleton)加载入Spring容器中

 

@EnableAutoConfiguration

        源码:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

        @EnableAotuConfiguration类中的核心注解为@import以及AutoConfigurationImportSelector类。@Import注解也是我们平时用得非常多的一个注解,同一模块下的引包,以及JDK自带包的引用都是需要用@Import注解使用的,这个注解是非常好理解的,然后我们再来说一说@Import的AutoConfigurationimportSelector类。

        首先我们来看看autoSonfigurationImportSelector类的源码:

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
    private static final AutoConfigurationImportSelector.AutoConfigurationEntry EMPTY_ENTRY = new AutoConfigurationImportSelector.AutoConfigurationEntry();
    private static final String[] NO_IMPORTS = new String[0];
    private static final Log logger = LogFactory.getLog(AutoConfigurationImportSelector.class);
    private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";
    private ConfigurableListableBeanFactory beanFactory;
    private Environment environment;
    private ClassLoader beanClassLoader;
    private ResourceLoader resourceLoader;
    private AutoConfigurationImportSelector.ConfigurationClassFilter configurationClassFilter;

    public AutoConfigurationImportSelector() {
    }

        首先这个类是实现了DeferredImportSelector接口,然后在看来他的核心方法 :

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
    return configurations;
}

        他的核心方法就是这个SpringFactoriesLoader.loadFactoryNames(),作用就是将META-INF/spring.factories的文件信息读取出来。然后作为Bean加载到Spring容器中。

 

总结:

        1、SpringBoot的运行机制要从他的核心注解@SpringBootAppliccation说起

        2、@SpringBootApplication的核心注解为:@ComponentScan、@Configuration、@EnabledAutoConfiguration

        3、@ComponentScan发现扫描包并将包下面的类加载进Spring容器作为Spring Bean 

        4、@Configuration + @Bean将自定义的配置类也加载入Spring容器中作为SpringBean

        5、@EnabledAutoConfiguration、@Import(AutoConfigurationIpmortSelector)、@AutoConfigurationPackage三个注解将Spring容器里面的Bean实现发现与加载

 

 

<think>好的,用户想了解Spring Boot运行机制和架构流程。首先,我需要回忆一下Spring Boot的核心设计理念,比如自动配置、起步依赖等。根据系统指令,我需要用中文回答,并且正确使用LaTeX格式的数学表达式,不过这里可能更多的是技术概念,可能用不上数学公式,但需要确保行内表达式正确。 用户提供的引用资料提到了Spring Boot作为脚手架框架,快速构建项目,预置配置,开箱即用。引用[3]提到Spring Boot直接运行,不需要传统Tomcat打包,这可能涉及内嵌服务器。引用[4]指出Spring Boot不提供核心功能,而是作为脚手架,所以需要解释其如何简化Spring应用的配置和启动。 接下来,需要组织回答的结构,分步骤说明运行机制。首先,启动流程,可能从main方法开始,使用SpringApplication.run(),然后触发自动配置。自动配置部分需要解释@EnableAutoConfiguration和条件化配置,比如@ConditionalOnClass。然后内嵌容器的部分,比如Tomcat或Jetty,如何启动。还有起步依赖和Starter的作用,简化依赖管理。 然后,架构流程可以分为初始化阶段、上下文准备、自动配置加载、内嵌容器启动。每个部分需要结合引用中的内容,比如引用[3]提到直接运行,所以需要强调内嵌服务器的作用。引用[4]的设计理念,说明Spring Boot如何作为脚手架整合Spring生态。 可能需要生成相关问题,比如自动配置原理、如何自定义Starter、与传统Spring MVC的区别等。这些问题要符合用户可能想深入的点。 需要检查LaTeX格式是否正确,比如如果有变量或术语可能需要用$包裹,但Spring Boot相关的术语可能不需要。确保引用标识正确添加,比如在提到启动引导流程时引用[^1],内嵌容器部分引用[^3]。 最后,确保回答结构清晰,分点说明,帮助用户逐步理解运行机制,并引用正确的资料。可能还需要注意术语的一致性,比如“起步依赖”对应Starter,自动配置对应@EnableAutoConfiguration等。</think>### Spring Boot运行机制及架构流程 Spring Boot运行机制围绕**简化配置**和**快速启动**两大核心目标,通过以下关键模块实现: --- #### 一、核心运行机制 1. **启动流程** 通过`main`方法调用`SpringApplication.run()`启动应用,触发以下流程: - 初始化应用上下文(`ApplicationContext`) - 加载`application.properties`/`application.yml`配置文件 - 执行自动配置(Auto-Configuration) - 启动内嵌Web容器(如Tomcat、Jetty) 2. **自动配置原理** 基于条件化注解(如`@ConditionalOnClass`)动态加载Bean: ```java @Configuration @ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class}) public class DataSourceAutoConfiguration { // 自动配置数据源 } ``` - **条件判断**:根据类路径、配置文件或环境变量决定是否启用配置[^4] - **优先级**:用户自定义Bean优先于自动配置的Bean 3. **内嵌容器** Spring Boot通过`spring-boot-starter-web`默认集成Tomcat: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> ``` - 容器启动时绑定到`server.port`指定端口 - 支持Jetty/Undertow等容器替换(通过排除Tomcat依赖) --- #### 二、架构流程 1. **初始化阶段** - 加载`SpringApplication`实例,注册`ApplicationListener` - 解析命令行参数和配置文件 2. **上下文准备** - 创建`AnnotationConfigServletWebServerApplicationContext` - 加载`@SpringBootApplication`标注的主配置类 3. **自动配置加载** - 通过`spring.factories`文件加载所有自动配置类 - 按需过滤无效配置(如缺少依赖库时跳过) 4. **内嵌容器启动** - 初始化Servlet环境(如DispatcherServlet) - 启动Web服务器并监听端口 --- #### 三、设计理念与优势 1. **约定优于配置** 预定义目录结构、配置默认值(如静态资源路径`/static`) 2. **起步依赖(Starter)** 通过依赖组合简化Maven/Gradle配置(如`spring-boot-starter-data-jpa`) 3. **健康检查与监控** 集成`actuator`模块提供端点(如`/health`、`/metrics`)[^2] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值