您好,登录后才能下订单哦!
Spring Boot 是一个用于简化 Spring 应用程序开发的框架。它通过提供默认配置和自动配置的方式,使得开发者能够快速搭建和运行 Spring 应用程序。Spring Boot 的底层原理涉及到多个方面,包括自动配置、依赖管理、嵌入式服务器、启动流程等。本文将深入探讨 Spring Boot 的底层原理,帮助读者更好地理解和使用 Spring Boot。
自动配置是 Spring Boot 的核心特性之一。它通过分析项目的依赖关系和配置文件,自动配置 Spring 应用程序的各个组件。自动配置的实现主要依赖于 @EnableAutoConfiguration 注解和 spring.factories 文件。
@EnableAutoConfiguration 注解是 Spring Boot 自动配置的入口。它通过 @Import 注解引入了 AutoConfigurationImportSelector 类,该类负责加载自动配置类。
@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 {};
}
spring.factories 文件是 Spring Boot 自动配置的关键文件之一。它位于 META-INF 目录下,用于定义自动配置类。Spring Boot 在启动时会扫描所有 spring.factories 文件,并加载其中定义的自动配置类。
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
...
Spring Boot 通过 spring-boot-starter 依赖管理机制,简化了项目的依赖配置。每个 spring-boot-starter 都包含了一组相关的依赖,开发者只需引入相应的 starter,即可自动引入所需的依赖。
spring-boot-starter-parent 是 Spring Boot 项目的父 POM,它定义了一系列默认的依赖管理和插件配置。通过继承 spring-boot-starter-parent,开发者可以简化项目的配置。
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.4</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
spring-boot-starter-web 是 Spring Boot 提供的用于开发 Web 应用的 starter。它包含了 Spring MVC、Tomcat 等依赖,开发者只需引入该 starter,即可快速搭建一个 Web 应用。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
Spring Boot 支持嵌入式服务器,开发者无需将应用部署到外部服务器中,即可直接运行应用。Spring Boot 默认使用 Tomcat 作为嵌入式服务器,但也支持 Jetty、Undertow 等其他服务器。
Tomcat 是 Spring Boot 默认的嵌入式服务器。Spring Boot 通过 spring-boot-starter-web 引入了 Tomcat 依赖,并在应用启动时自动配置和启动 Tomcat。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
Jetty 是另一个常用的嵌入式服务器。开发者可以通过排除 spring-boot-starter-tomcat 并引入 spring-boot-starter-jetty,来使用 Jetty 作为嵌入式服务器。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
Spring Boot 的启动流程主要包括以下几个步骤:
application.properties 或 application.yml 配置文件,并根据配置内容进行相应的配置。AnnotationConfigApplicationContext 或 AnnotationConfigServletWebServerApplicationContext,用于管理 Spring Bean。spring.factories 文件中的配置,加载并执行自动配置类。SpringApplication.run() 方法,启动应用并进入运行状态。Spring Boot 的自动配置是通过 @Conditional 注解和 Condition 接口实现的。@Conditional 注解用于根据条件决定是否加载某个配置类或 Bean,而 Condition 接口则用于定义具体的条件逻辑。
@Conditional 注解是 Spring 框架提供的注解,用于根据条件决定是否加载某个配置类或 Bean。Spring Boot 在此基础上扩展了一系列条件注解,如 @ConditionalOnClass、@ConditionalOnMissingBean 等。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {
    Class<?>[] value() default {};
    String[] name() default {};
}
Condition 接口是 Spring 框架提供的接口,用于定义条件逻辑。开发者可以通过实现 Condition 接口,自定义条件判断逻辑。
public interface Condition {
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
Spring Boot 的自动配置加载过程主要包括以下几个步骤:
spring.factories 文件:Spring Boot 会扫描所有 META-INF/spring.factories 文件,并加载其中定义的自动配置类。@Conditional 注解的条件,过滤掉不符合条件的自动配置类。Spring Boot 的自动配置机制是可扩展的,开发者可以通过自定义自动配置类,扩展 Spring Boot 的自动配置功能。
开发者可以通过定义自动配置类,并添加 @Configuration 和 @Conditional 注解,来实现自定义的自动配置。
@Configuration
@ConditionalOnClass(MyService.class)
public class MyAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public MyService myService() {
        return new MyService();
    }
}
开发者可以通过在 META-INF/spring.factories 文件中注册自动配置类,使其在应用启动时被加载。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration
Spring Boot 的依赖管理是通过 Maven 或 Gradle 的依赖管理机制实现的。Spring Boot 提供了一系列 spring-boot-starter 依赖,每个 starter 都包含了一组相关的依赖,开发者只需引入相应的 starter,即可自动引入所需的依赖。
spring-boot-starter-parent 是 Spring Boot 项目的父 POM,它定义了一系列默认的依赖管理和插件配置。通过继承 spring-boot-starter-parent,开发者可以简化项目的配置。
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.4</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
spring-boot-dependencies 是 Spring Boot 提供的依赖管理 POM,它定义了一系列常用的依赖版本。通过引入 spring-boot-dependencies,开发者可以统一管理项目的依赖版本。
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.5.4</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
Spring Boot 的依赖管理机制是可扩展的,开发者可以通过自定义 starter,扩展 Spring Boot 的依赖管理功能。
开发者可以通过定义 starter,并添加 spring.factories 文件,来实现自定义的依赖管理。
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>my-library</artifactId>
    </dependency>
</dependencies>
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration
开发者可以通过在 META-INF/spring.factories 文件中注册 starter,使其在应用启动时被加载。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration
Spring Boot 的嵌入式服务器是通过 spring-boot-starter-web 依赖实现的。Spring Boot 默认使用 Tomcat 作为嵌入式服务器,但也支持 Jetty、Undertow 等其他服务器。
Tomcat 是 Spring Boot 默认的嵌入式服务器。Spring Boot 通过 spring-boot-starter-web 引入了 Tomcat 依赖,并在应用启动时自动配置和启动 Tomcat。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
Jetty 是另一个常用的嵌入式服务器。开发者可以通过排除 spring-boot-starter-tomcat 并引入 spring-boot-starter-jetty,来使用 Jetty 作为嵌入式服务器。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
Spring Boot 提供了丰富的配置选项,开发者可以通过 application.properties 或 application.yml 文件,配置嵌入式服务器的各项参数。
开发者可以通过 server.port 属性,配置嵌入式服务器的端口。
server.port=8081
开发者可以通过 server.servlet.context-path 属性,配置嵌入式服务器的上下文路径。
server.servlet.context-path=/myapp
开发者可以通过 server.ssl 属性,配置嵌入式服务器的 SSL 证书。
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=secret
Spring Boot 的嵌入式服务器机制是可扩展的,开发者可以通过自定义配置类,扩展 Spring Boot 的嵌入式服务器功能。
开发者可以通过定义配置类,并添加 @Configuration 和 @Conditional 注解,来实现自定义的嵌入式服务器配置。
@Configuration
@ConditionalOnClass(Tomcat.class)
public class MyTomcatConfiguration {
    @Bean
    public TomcatServletWebServerFactory tomcatFactory() {
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
        factory.setPort(8081);
        return factory;
    }
}
开发者可以通过在 META-INF/spring.factories 文件中注册配置类,使其在应用启动时被加载。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyTomcatConfiguration
Spring Boot 的启动流程是通过 SpringApplication 类实现的。SpringApplication 类负责加载配置文件、创建应用上下文、执行自动配置、启动嵌入式服务器等操作。
SpringApplication 类是 Spring Boot 启动流程的核心类。它提供了 run() 方法,用于启动 Spring Boot 应用。
public class SpringApplication {
    public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
        return run(new Class<?>[] { primarySource }, args);
    }
    public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        return new SpringApplication(primarySources).run(args);
    }
    public SpringApplication(Class<?>... primarySources) {
        this(null, primarySources);
    }
    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.resourceLoader = resourceLoader;
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = deduceMainApplicationClass();
    }
    public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        configureHeadlessProperty();
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting();
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
            configureIgnoreBeanInfo(environment);
            Banner printedBanner = printBanner(environment);
            context = createApplicationContext();
            exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
            prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            refreshContext(context);
            afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
            }
            listeners.started(context);
            callRunners(context, applicationArguments);
        } catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, listeners);
            throw new IllegalStateException(ex);
        }
        try {
            listeners.running(context);
        } catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, null);
            throw new IllegalStateException(ex);
        }
        return context;
    }
}
Spring Boot 的启动流程主要包括以下几个步骤:
application.properties 或 application.yml 配置文件,并根据配置内容进行相应的配置。AnnotationConfigApplicationContext 或 AnnotationConfigServletWebServerApplicationContext,用于管理 Spring Bean。spring.factories 文件中的配置,加载并执行自动配置类。SpringApplication.run() 方法,启动应用并进入运行状态。Spring Boot 的启动流程是可扩展的,开发者可以通过自定义 ApplicationRunner 或 CommandLineRunner,扩展 Spring Boot 的启动流程。
ApplicationRunner 是 Spring Boot 提供的接口,用于在应用启动后执行一些操作。开发者可以通过实现 ApplicationRunner 接口,自定义启动后的操作。
@Component
public class MyApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("Application started with arguments: " + Arrays.toString(args.getSourceArgs()));
    }
}
CommandLineRunner 是 Spring Boot 提供的另一个接口,用于在应用启动后执行一些操作。开发者可以通过实现 CommandLineRunner 接口,自定义启动后的操作
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。