spring boot的启动过程及原理剖析

1、spring boot是什么?

Spring Boot 是一种基于 Java 的框架,可以简化 Spring 应用程序的初始搭建和开发过程,提供了快速构建应用的能力。Spring Boot 的主要设计目标是使应用程序的开发变得更加快速、便捷,同时尽可能地减少开发人员在配置上的工作量。它通过提供一个预先配置好的开发环境,使得开发人员可以集中精力于业务逻辑的开发而不必过多关注基础设施和应用的配置。

Spring Boot 提供了很多优秀的特性和功能,如自动配置、起步依赖、应用监控、外部化配置等等,这些功能都可以帮助开发人员更快速地搭建出高质量的应用程序。同时,Spring Boot 与 Spring 框架高度集成,开发人员可以使用 Spring 框架提供的各种功能来构建应用,这使得 Spring Boot 成为了 Java 开发中非常流行的框架之一。

2、spring boot和spring的区别

虽然Spring和Spring Boot都是Java开发中的优秀框架,但它们之间的区别也很明显:

首先,Spring是一个庞大的生态系统,包括了很多模块和组件,如Spring Core、Spring MVC、Spring Data等,而Spring Boot则是在Spring基础上进行了封装和增强,可以让开发者更加便捷地搭建和部署应用程序,大大减少了繁琐的配置工作。

其次,Spring Boot的自动配置能力非常强大,可以根据应用程序所需的依赖和环境自动进行配置,而Spring则需要手动配置很多细节和参数。这使得Spring Boot的开发效率更高,同时也让开发者可以更加专注于业务开发。

另外,Spring Boot的优点还包括内嵌的Tomcat、Jetty等服务器,可以方便地打包和部署应用程序,还支持各种开发工具和框架,如Maven、Gradle、Thymeleaf等。

3、spring boot的特性

  1. 自动化配置:Spring Boot提供了很多自动配置的能力,可以根据应用程序的需要自动配置各种组件,如数据库、消息队列、缓存等,使得开发者可以专注于业务代码而不必过多关注配置细节。

  2. 内嵌服务器:Spring Boot集成了内嵌的Tomcat、Jetty等服务器,无需额外安装和配置服务器即可进行开发和测试。

  3. Actuator监控:Spring Boot提供了Actuator组件,可以实时监控应用程序的运行状态,包括请求量、CPU和内存使用等,方便进行性能调优和故障排查。

  4. 简化依赖管理:Spring Boot可以自动管理应用程序的依赖,根据需要自动添加或升级依赖,减少了开发者对依赖管理的繁琐工作。

  5. 开发效率高:Spring Boot的自动化配置和依赖管理等特性,可以大大减少开发者的配置工作,从而提高开发效率,加速项目开发周期。

  6. 生态系统丰富:Spring Boot作为Spring生态系统的一部分,可以无缝地集成其他Spring组件和第三方库,如Spring MVC、Spring Security、MyBatis等,提供了一个完整而强大的开发环境。

4、spring boot启动流程

Spring Boot的启动流程可以概括为以下几个步骤:

1、加载配置文件

2、创建Spring应用程序上下文

3、扫描组件

4、加载自动配置类

5、加载启动器

6、注册Bean

7、启动内置的Web服务器

8、发布启动事件

以下是每个步骤的详细讲解:

1、加载配置文件

Spring Boot会在classpath下查找application.properties或application.yml文件,并加载其中的配置信息。如果需要自定义配置文件的名称或位置,可以通过设置spring.config.name和spring.config.location属性来指定。这些配置文件中包含了应用程序的配置信息,例如服务器端口号、数据库连接地址等。

下面是Spring Boot加载配置文件的具体流程:

1.首先,Spring Boot会根据约定的位置加载默认的配置文件。默认情况下,Spring Boot会在以下位置寻找配置文件:

如果配置文件存在,Spring Boot会将其加载到应用程序上下文中。

  • classpath:/application.properties
  • classpath:/application.yml
  • classpath:/application.yaml
  • classpath:/application.json
  • classpath:/application.xml
  • file:./application.properties
  • file:./application.yml
  • file:./application.yaml
  • file:./application.json
  • file:./application.xml

2.如果默认的配置文件不存在,Spring Boot会加载用户指定的配置文件。可以通过在启动命令行参数中使用--spring.config.name和--spring.config.location参数来指定应用程序的配置文件名称和路径。

例如,下面的命令行参数指定应用程序的配置文件名称为myapp,路径为/home/user/config/:

java -jar myapp.jar --spring.config.name=myapp --spring.config.location=/home/user/config/

 ​​​​​​3.最后,Spring Boot会对所有加载的配置文件进行合并,并将其存储在应用程序上下文的Environment对象中。应用程序可以通过Environment对象来访问所有配置属性。

下面是一个简单的示例代码,演示如何加载配置文件并读取其中的配置属性:

@SpringBootApplication
public class MyApp {

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(MyApp.class);
        app.run(args);

        Environment env = app.getContext().getEnvironment();
        String appName = env.getProperty("spring.application.name");
        int port = env.getProperty("server.port", Integer.class);

        System.out.println("Application Name: " + appName);
        System.out.println("Server Port: " + port);
    }
}

在这个示例中,使用@SpringBootApplication注解标记了应用程序的入口类,并通过SpringApplication类来启动应用程序。在应用程序启动之后,通过Environment对象来读取配置属性,例如spring.application.name和server.port。如果这些属性在配置文件中存在,就会返回其对应的值。如果不存在,就会返回null或者默认值。

2、创建Spring应用程序上下文

创建Spring应用程序上下文,它是整个Spring Boot应用程序的核心。Spring应用程序上下文是一个IoC容器,用于管理所有的Bean对象,它会根据配置文件和注解来创建Bean对象,并将它们注入到应用程序中。下面是创建Spring应用程序上下文的详细流程:

  1. Spring Boot使用SpringApplication类来启动应用程序。在启动过程中,SpringApplication类会根据指定的参数创建一个Spring应用程序上下文。

  2. Spring Boot会检查应用程序中是否存在@Configuration注解的类。如果存在,就会将这些类作为配置类加载到Spring应用程序上下文中。配置类中的@Bean注解会告诉Spring容器需要创建的Bean对象。

  3. Spring Boot会根据应用程序中的@ComponentScan注解来扫描指定的包,查找带有@Component、@Service、@Repository和@Controller等注解的类,并将这些类作为Bean对象加载到Spring应用程序上下文中。

  4. Spring Boot会自动加载许多常用的Bean对象,例如DataSource、JdbcTemplate、HibernateTemplate和JPA EntityManager等,这些Bean对象可以直接在应用程序中使用。

下面是一个简单的示例代码,演示如何创建Spring应用程序上下文:

@SpringBootApplication
public class MyApp {

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(MyApp.class);
        ConfigurableApplicationContext context = app.run(args);

        MyService service = context.getBean(MyService.class);
        service.doSomething();

        context.close();
    }

    @Bean
    public MyService myService() {
        return new MyService();
    }
}

@Service
public class MyService {
    public void doSomething() {
        System.out.println("Hello, world!");
    }
}

在这个示例中,使用@SpringBootApplication注解标记了应用程序的入口类,并使用@SpringBootConfiguration注解标记了一个配置类,该配置类中定义了一个名为myService的Bean对象。还创建了一个名为MyService的Service类,并将其标记为@Service注解。在应用程序启动后,我们可以通过上下文获取MyService对象,并调用它的doSomething()方法。

需要注意的是,Spring Boot的自动配置机制非常强大,可以自动配置许多常用的Bean对象,大大简化了应用程序的开发。

3、扫描组件

在创建Spring应用程序上下文之后,Spring Boot会自动扫描应用程序中的组件,例如@Controller、@Service、@Repository等。如果需要修改默认的扫描路径,并将它们纳入Spring管理的Bean中,使得这些组件能够被注入到其他组件中。可以通过设置@ComponentScan注解的basePackages属性来指定。

扫描的过程主要由ClassPathBeanDefinitionScanner类来实现。它会在指定的包路径下进行扫描,并解析每一个类文件,确定哪些类符合要求成为一个Spring Bean。

以下是一个简单的示例代码,演示如何使用@ComponentScan注解来指定需要扫描的包路径:

@Configuration
@ComponentScan(basePackages = "com.example.demo")
public class AppConfig {
    //其他配置项
}

在这个例子中,@ComponentScan注解告诉Spring Boot应该扫描com.example.demo包下的所有组件。

具体来说,ClassPathBeanDefinitionScanner会通过ClassPathScanningCandidateComponentProvider类来实现组件的扫描。该类会扫描指定包路径下的所有类,并根据类上的注解信息判断哪些类需要被注册为Spring Bean。它会使用一个TypeFilter接口来过滤掉不符合条件的类,例如排除掉非公共类、抽象类、接口类等。而符合条件的类将会被封装为一个BeanDefinition对象,然后注册到应用程序上下文中。

在实际开发中,可以通过在应用程序启动类上添加@ComponentScan注解来指定扫描路径,或者通过在配置类上添加@Import注解来引入其他的配置类。这些注解的使用可以非常灵活,以适应各种不同的场景需求。

4、加载自动配置类

当Spring Boot启动时,会加载classpath下所有META-INF/spring.factories文件中配置的自动配置类。这些自动配置类都实现了AutoConfigurationImportSelector接口,其中的selectImports方法返回需要自动配置的类名数组。

下面是一个简单的例子,展示了如何自定义自动配置类并将其配置到spring.factories文件中:

src/main/resources目录下创建META-INF目录,在META-INF目录下创建spring.factories文件,添加以下内容:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.example.demo.MyAutoConfiguration

然后创建一个自动配置类MyAutoConfiguration,实现需要的自动配置逻辑,例如:

@Configuration
public class MyAutoConfiguration {

    @Bean
    public MyService myService() {
        return new MyService();
    }
}

在上述配置中,MyAutoConfiguration实现了@Configuration注解,表示这是一个Spring配置类。在其中定义了一个MyService类型的Bean,并使用@Bean注解标记它。

在启动应用程序时,Spring Boot会扫描META-INF/spring.factories文件中定义的EnableAutoConfiguration键对应的值,并加载指定的自动配置类,将其转换为Spring配置。在本例中,Spring Boot会自动加载MyAutoConfiguration类,并注册其中的MyService Bean。

需要注意的是,自动配置类可以通过Spring的Condition注解来控制是否应该自动配置。Condition注解的逻辑可以根据不同的条件进行判断,例如判断是否存在特定的类、是否存在特定的配置属性等等。这样可以根据应用程序的具体需要选择性地自动配置某些类。

5、加载启动器

在加载完自动配置类后,Spring Boot会接着加载启动器。启动器是一个特殊的自动配置类,它会根据用户在配置文件中配置的启动器相关属性来加载对应的组件和配置。启动器的加载过程主要分为以下两个步骤:

  1. 根据配置文件中的属性加载启动器依赖的组件和配置
  2. 将这些组件和配置注入到Spring应用程序上下文中

下面是一个简单的示例代码,展示如何创建一个启动器:

@SpringBootApplication
public class MyApplication {
    
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(MyApplication.class);
        app.run(args);
    }
    
    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

在这个例子中,MyApplication类被标记了@SpringBootApplication注解,这意味着它是一个启动器。在main方法中,我们创建了一个SpringApplication实例,并将MyApplication类作为参数传递给它。在MyApplication类中,我们还定义了一个MyService类型的Bean,它会被注入到Spring应用程序上下文中。

在启动器加载的过程中,SpringApplication实例会首先根据配置文件中的属性加载依赖的组件和配置。然后,它会将这些组件和配置注入到Spring应用程序上下文中,使它们可以被其他组件所引用。

6、注册Bean

当Spring Boot创建完Spring应用程序上下文之后,会自动注册一些Bean来支持Web应用程序的运行,例如EmbeddedServletContainerFactory、DispatcherServlet、RequestMappingHandlerAdapter等。这些Bean的注册是通过自动配置类完成的,例如WebMvcAutoConfiguration、ServletWebServerFactoryAutoConfiguration等。

自动配置类中会使用@Configuration注解进行标注,并通过@Bean注解注册Bean。以WebMvcAutoConfiguration为例,其中会注册如下的Bean:

@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
        ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
    // ...省略其他代码

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
    @ConditionalOnMissingBean(name = DispatcherServlet.HANDLER_MAPPING_BEAN_NAME, value = HandlerMapping.class)
    public HandlerMapping defaultServletHandlerMapping() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
                configurer.enable();
            }
        };
    }

    // ...省略其他代码
}

可以看到,在WebMvcAutoConfiguration中定义了一个名为defaultServletHandlerMapping的Bean,使用@Bean注解进行标注。在这个Bean的定义中,使用了@Scope注解指定了Bean的作用域,使用了@ConditionalOnMissingBean注解进行条件注入。在这个Bean中,会创建一个WebMvcConfigurerAdapter的实例,并实现configureDefaultServletHandling方法。最终,这个方法会返回一个HandlerMapping对象,用来处理默认的Servlet请求。

如果需要注册自定义的Bean,可以通过自定义的@Configuration注解的类来实现。例如,下面的示例中定义了一个名为myBean的Bean,并将其注册到Spring应用程序上下文中:

@Configuration
public class MyConfiguration {
    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}

这个示例中,使用@Configuration注解定义了一个名为MyConfiguration的类,并使用@Bean注解定义了一个名为myBean的Bean。在myBean的定义中,创建了一个MyBean的实例,并返回该实例。当Spring Boot启动时,会自动扫描并加载MyConfiguration类,从而自动注册myBean这个Bean到Spring应用程序上下文中。

7、启动内置的Web服务器

Spring Boot内置了多种Web服务器,例如Tomcat、Jetty、Undertow等。在启动过程中,Spring Boot会自动检测应用程序中是否存在Web服务器,并根据需要进行自动配置。

具体来说,Spring Boot通过自动配置类来实现对Web服务器的自动配置。以Tomcat为例,Spring Boot提供了TomcatAutoConfiguration自动配置类,它会根据应用程序中的配置文件进行Tomcat服务器的自动配置。TomcatAutoConfiguration的源代码如下:

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@AutoConfigureAfter({ ServletWebServerFactoryAutoConfiguration.class, EmbeddedWebServerFactoryCustomizerAutoConfiguration.class })
public class TomcatAutoConfiguration {

    ...

    @Bean
    @ConditionalOnMissingBean
    public TomcatServletWebServerFactory tomcatServletWebServerFactory(
            ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers,
            ObjectProvider<TomcatContextCustomizer> contextCustomizers,
            ObjectProvider<TomcatProtocolHandlerCustomizer<?>> protocolHandlerCustomizers) {
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
        factory.getTomcatConnectorCustomizers()
                .addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));
        factory.getTomcatContextCustomizers()
                .addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));
        factory.getTomcatProtocolHandlerCustomizers()
                .addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));
        return factory;
    }

    ...
}

TomcatAutoConfiguration类上标注了@Configuration注解,表示它是一个配置类;@ConditionalOnClass注解表示只有当应用程序中存在Servlet、Tomcat和UpgradeProtocol类时,才会加载该配置类;@ConditionalOnMissingBean注解表示当容器中不存在ServletWebServerFactory类的Bean时,才会加载该配置类;@AutoConfigureOrder注解表示该配置类的优先级最高;@AutoConfigureAfter注解表示该配置类会在ServletWebServerFactoryAutoConfiguration和EmbeddedWebServerFactoryCustomizerAutoConfiguration配置类之后进行加载。

TomcatAutoConfiguration类中定义了一个tomcatServletWebServerFactory()方法,用于创建TomcatServletWebServerFactory实例。在该方法中,使用了ObjectProvider类获取TomcatConnectorCustomizer、TomcatContextCustomizer和TomcatProtocolHandlerCustomizer实例,并将它们添加到TomcatServletWebServerFactory实例中。这些实例在后面的Tomcat服务器创建和启动过程中会被使用到。

在应用程序启动过程中,当检测到应用程序中存在Tomcat依赖时,Spring Boot会自动加载TomcatAutoConfiguration配置类,并调用其中的tomcatServletWebServerFactory()方法来创建TomcatServletWebServerFactory实例。随后,Spring Boot会根据配置文件中的属性,对TomcatServletWebServerFactory实例进行自动配置,并创建Tomcat服务器,并启动Tomcat服务器,开始监听HTTP请求。这样,整个Spring Boot应用程序就启动完成了,可以开始提供服务了。

需要注意的是,在启动内置的Web服务器后,Spring Boot应用程序不会立即退出,而是一直处于运行状态,等待接收来自客户端的请求。如果应用程序需要停止,可以通过调用SpringApplication的close()方法来关闭应用程序。另外,Spring Boot还提供了一些管理端点,可以通过访问特定的URL来获取应用程序的运行状态信息、调用特定的功能等。

8、发布启动事件

当Spring Boot启动完毕后,会发布一个ApplicationStartedEvent事件,通知所有的监听器应用程序已经启动。我们可以通过实现ApplicationListener接口来监听该事件。

下面是一个简单的示例代码,用于演示如何监听ApplicationStartedEvent事件:

@Component
public class MyApplicationListener implements ApplicationListener<ApplicationStartedEvent> {

    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        // 处理应用程序启动事件
        System.out.println("ApplicationStartedEvent received!");
    }
}

在上面的代码中,我们定义了一个名为MyApplicationListener的组件,并实现了ApplicationListener接口。在onApplicationEvent方法中,我们可以处理ApplicationStartedEvent事件。

当Spring Boot启动完成后,会自动创建一个ApplicationContext对象,并将其存储在SpringApplication实例中。当ApplicationContext对象创建完成后,Spring Boot会依次加载配置文件、注册Bean、自动配置等操作。当所有的操作都完成后,Spring Boot会发布ApplicationStartedEvent事件,通知所有的监听器应用程序已经启动。

注意,ApplicationStartedEvent是在所有的应用程序上下文(包括Web应用程序上下文和非Web应用程序上下文)都创建完成后才会被发布。如果需要在特定的上下文创建完成后接收事件通知,可以使用不同的事件,例如ContextStartedEvent和ServletContextInitializedEvent。

ApplicationStartedEvent只是启动事件的一种类型,Spring Boot还提供了很多其他的事件类型,例如ApplicationStartingEvent、ApplicationEnvironmentPreparedEvent、ApplicationPreparedEvent等。

如果我们需要监听其它事件,只需要将泛型改为对应的事件类型即可。同时,我们需要将监听器类添加到Spring应用程序上下文中,可以通过@Component或@Bean注解来实现。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
`afterRefresh` 是 Spring Boot 启动过程中的一个重要方法,它是在 Spring 应用上下文完成刷新之后被调用的。具体来说,`afterRefresh` 方法是在 `AbstractApplicationContext` 类的 `finishRefresh` 方法中被调用的,代码如下: ```java protected void finishRefresh() { // ... // Initialize lifecycle processor for this context. initLifecycleProcessor(); // Propagate refresh to lifecycle processor first. getLifecycleProcessor().onRefresh(); // Publish the final event. publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. if (!isRunning()) { stop(); } // ... // Finally, invoke the afterRefresh callbacks. invokeAfterRefreshCallbacks(); } ``` 在 `afterRefresh` 方法中,Spring Boot 会调用 `ApplicationContext` 中所有实现了 `org.springframework.context.support.ApplicationContextAware` 接口的 Bean 的 `setApplicationContext` 方法,将应用上下文传入这些 Bean 中。这样,这些 Bean 就能够获取到应用上下文,并在需要时使用它。 另外,Spring Boot 还会回调所有实现了 `org.springframework.boot.context.event.ApplicationContextInitializedListener` 接口的 Bean 的 `afterApplicationContextInitialized` 方法,这些 Bean 可以在应用上下文初始化之后进行一些自定义操作。 总之,`afterRefresh` 方法是 Spring Boot 启动过程中非常重要的一个方法,它标志着应用上下文已经完成了初始化,可以进入正常的运行状态了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汤了个圆了个汤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值