当前位置: 首页 > article >正文

Springboot 的启动流程【超级详细 | 附带思维导图】

在这里插入图片描述

2. 创建SpringApplication

  1. 推断应用类型(WebApplicationType)
// SpringBoot会检查classpath中的类来判断应用类型
if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", null)) {
    return WebApplicationType.REACTIVE;  // 响应式Web应用
} else if (ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", null)) {
    return WebApplicationType.SERVLET;   // 传统Web应用
} else {
    return WebApplicationType.NONE;      // 普通应用
}

拓展

  • REACTIVE 响应式Web应用:

Spring Cloud Gateway中确实使用了响应式编程模型。Spring Cloud Gateway是基于Spring WebFlux构建的,它采用了响应式编程范式,利用了Project Reactor和Netty等技术。

Spring Cloud Gateway中,请求的处理是通过一系列的过滤器(Filter)来实现的。每个过滤器都可以对请求进行拦截、转换、路由等操作。这些过滤器组成了一个过滤器链(Filter Chain),请求会依次通过这些过滤器。

在编写自定义过滤器时,你可以通过chain.filter(exchange)方法将请求传递给过滤器链中的下一个过滤器,这个方法返回一个Mono<Void>对象,表示异步地处理请求。

下面是一个自定义过滤器的示例:

@Component
public class CustomFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 在此处进行请求的预处理
        ServerHttpRequest request = exchange.getRequest().mutate()
                .header("Custom-Header", "Value")
                .build();
        
        return chain.filter(exchange.mutate().request(request).build())
                .then(Mono.fromRunnable(() -> {
                    // 在此处进行响应的后处理
                }));
    }
}

在这个示例中,filter方法接收一个ServerWebExchange对象和一个GatewayFilterChain对象。通过chain.filter(exchange)将请求传递给下一个过滤器,并在请求处理完成后进行响应的后处理。

总之,在Spring Cloud Gateway中,由于使用了响应式编程模型,因此需要使用MonoFlux等响应式类型,并通过chain.filter(exchange)方法将请求传递给过滤器链中的下一个过滤器。

3.准备环境(ConfigurableEnvironment)

  1. 环境配置来源(按优先级从高到低):
// 命令行参数(最高优先级)
java -jar app.jar --server.port=8080

// 系统环境变量
System.getenv("JAVA_HOME")

// application.properties/yml 配置文件
// application-{profile}.properties/yml 特定环境配置
  1. 具体加载过程:
public class EnvironmentPrepareExample {
    
    // 创建环境对象
    ConfigurableEnvironment environment = new StandardEnvironment();
    
    // 添加属性源
    environment.getPropertySources().addLast(
        new ResourcePropertySource("application.properties")
    );
    
    // 设置激活的配置文件
    environment.setActiveProfiles("dev", "local");
    
    // 获取配置值
    String serverPort = environment.getProperty("server.port");
    String dbUrl = environment.getProperty("spring.datasource.url");
}
  1. 常见配置示例:
# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test
    username: root
    password: 123456
  
server:
  port: 8080
  
logging:
  level:
    root: INFO

# 自定义配置
custom:
  property: value
  1. 配置优先级(从高到低):
1. 命令行参数
2. SPRING_APPLICATION_JSON 环境变量
3. java:comp/env JNDI属性
4. System.getProperties() 系统属性
5. 操作系统环境变量
6. random.* 随机属性
7. application-{profile}.properties/yml
8. application.properties/yml
  1. 获取配置的方式:
@Value("${server.port}")
private String serverPort;

@ConfigurationProperties(prefix = "custom")
public class CustomProperties {
    private String property;
    // getter/setter
}

@Autowired
private Environment environment;
String value = environment.getProperty("custom.property");
  1. 配置刷新机制:
@RefreshScope  // 支持配置热更新
@Component
public class ConfigComponent {
    @Value("${dynamic.property}")
    private String dynamicProperty;
}

关键点:

  • 环境准备是为了统一管理各种配置源
  • 提供了灵活的配置方式和优先级机制
  • 支持profile进行环境切换
  • 可以通过多种方式获取配置
  • 支持配置热更新
  • 配置值可以被覆盖,高优先级的配置会覆盖低优先级的配置

这个阶段就是在应用启动前,把所有的配置信息都准备好,为后续的Bean创建和依赖注入做准备。

4. 创建并刷新 ApplicationContext

  1. 创建 ApplicationContext:
// 根据应用类型创建对应的上下文
ConfigurableApplicationContext context;
if (webApplicationType == WebApplicationType.SERVLET) {
    context = new AnnotationConfigServletWebServerApplicationContext();
} else if (webApplicationType == WebApplicationType.REACTIVE) {
    context = new AnnotationConfigReactiveWebServerApplicationContext();
} else {
    context = new AnnotationConfigApplicationContext();
}
  1. 加载配置类:
@Configuration  // 配置类
public class AppConfig {
    
    @Bean  // 定义Bean
    public UserService userService() {
        return new UserService();
    }
    
    @Bean
    public OrderService orderService() {
        return new OrderService(userService());  // 依赖注入
    }
}

// 启动类中的自动配置
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  1. 注册Bean的几种方式:
// 1. @Component注解
@Component
public class UserService {
}

// 2. @Bean注解
@Bean
public OrderService orderService() {
    return new OrderService();
}

// 3. 配置类导入
@Import({PaymentConfig.class})
public class AppConfig {
}

// 4. 实现FactoryBean
public class MyFactoryBean implements FactoryBean<MyObject> {
    @Override
    public MyObject getObject() {
        return new MyObject();
    }
}
  1. 依赖注入方式:
// 1. 构造器注入(推荐)
@Service
public class UserService {
    private final UserRepository userRepository;
    
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

// 2. 字段注入
@Service
public class OrderService {
    @Autowired
    private UserService userService;
}

// 3. Setter注入
@Service
public class ProductService {
    private PriceService priceService;
    
    @Autowired
    public void setPriceService(PriceService priceService) {
        this.priceService = priceService;
    }
}
  1. Bean的生命周期回调:
@Component
public class LifecycleBean implements InitializingBean, DisposableBean {
    
    @PostConstruct  // 构造后
    public void init() {
        System.out.println("Bean初始化");
    }
    
    @Override  // InitializingBean接口
    public void afterPropertiesSet() {
        System.out.println("属性设置完成");
    }
    
    @PreDestroy  // 销毁前
    public void cleanup() {
        System.out.println("Bean清理");
    }
    
    @Override  // DisposableBean接口
    public void destroy() {
        System.out.println("Bean销毁");
    }
}
  1. 上下文刷新主要步骤:
// AbstractApplicationContext的refresh()方法
public void refresh() {
    // 1. 准备刷新上下文
    prepareRefresh();
    
    // 2. 创建BeanFactory
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
    // 3. 准备BeanFactory
    prepareBeanFactory(beanFactory);
    
    // 4. 执行BeanFactoryPostProcessor
    invokeBeanFactoryPostProcessors(beanFactory);
    
    // 5. 注册BeanPostProcessor
    registerBeanPostProcessors(beanFactory);
    
    // 6. 初始化消息源
    initMessageSource();
    
    // 7. 初始化事件多播器
    initApplicationEventMulticaster();
    
    // 8. 初始化特定的Bean
    onRefresh();
    
    // 9. 注册监听器
    registerListeners();
    
    // 10. 完成Bean实例化
    finishBeanFactoryInitialization(beanFactory);
    
    // 11. 完成刷新
    finishRefresh();
}

关键点:

  • ApplicationContext是Spring的核心容器
  • 负责Bean的创建、配置和管理
  • 支持多种依赖注入方式
  • 提供Bean生命周期管理
  • 刷新过程包含多个重要步骤
  • 自动配置和手动配置共同作用

这个阶段完成后,所有的Bean都已经创建完成并完成了依赖注入,应用程序已经准备好处理请求了。

5. 在刷新上下文时启动嵌入式 Web 服务器

  1. 自动配置Tomcat:
@Configuration
public class EmbeddedTomcatConfiguration {
    
    @Bean
    public TomcatServletWebServerFactory tomcatFactory() {
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
        // 配置Tomcat
        factory.setPort(8080);                    // 设置端口
        factory.setContextPath("/api");           // 设置上下文路径
        factory.addConnectorCustomizers(connector -> {
            connector.setMaxPostSize(5000000);    // 设置最大POST大小
        });
        return factory;
    }
}
  1. 注册Servlet:
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
        throws ServletException, IOException {
        resp.getWriter().write("Hello from Servlet!");
    }
}

// 通过配置类注册
@Configuration
public class ServletConfig {
    @Bean
    public ServletRegistrationBean<HelloServlet> helloServlet() {
        ServletRegistrationBean<HelloServlet> registration = 
            new ServletRegistrationBean<>(new HelloServlet(), "/hello");
        registration.setLoadOnStartup(1);
        return registration;
    }
}
  1. 注册Filter:
@Component
public class LoggingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                        FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        log.info("Request URI: {}", req.getRequestURI());
        chain.doFilter(request, response);
    }
}

// 通过配置类注册
@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<LoggingFilter> loggingFilter() {
        FilterRegistrationBean<LoggingFilter> registration = 
            new FilterRegistrationBean<>(new LoggingFilter());
        registration.addUrlPatterns("/*");
        registration.setOrder(1);
        return registration;
    }
}
  1. 自定义嵌入式服务器配置:
# application.yml
server:
  port: 8080
  servlet:
    context-path: /api
  tomcat:
    max-threads: 200
    min-spare-threads: 10
    max-connections: 10000
    accept-count: 100
  1. 编程方式配置:
@Configuration
public class ServerConfiguration {
    @Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> customizer() {
        return factory -> {
            // 配置Tomcat
            factory.addConnectorCustomizers(connector -> {
                connector.setMaxPostSize(5000000);
            });
            
            // 配置错误页面
            factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404"));
            
            // 配置SSL
            factory.setSsl(getSslStoreProvider());
        };
    }
}
  1. 监听服务器启动:
@Component
public class ServerStartupListener implements 
    ApplicationListener<WebServerInitializedEvent> {
    
    @Override
    public void onApplicationEvent(WebServerInitializedEvent event) {
        int port = event.getWebServer().getPort();
        log.info("Web server started on port: {}", port);
    }
}
  1. 常见的Web容器配置:
// 切换到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>

关键点:

  • 默认使用Tomcat作为嵌入式服务器
  • 支持Servlet和Filter的注册
  • 提供多种配置方式(配置文件、编程方式)
  • 可以自定义错误页面
  • 支持SSL配置
  • 可以切换到其他Web容器(如Jetty、Undertow)
  • 提供监听器机制监控服务器状态

这个阶段完成后:

  • Web服务器启动并监听指定端口
  • Servlet和Filter被正确注册
  • 应用准备好接收HTTP请求
  • 所有的Web相关配置生效

6.发布应用已启动事件

发布应用已启动事件(ApplicationStartedEvent)的主要作用是提供一个时机点,让我们能在应用完全启动后,但在开始接收请求之前执行一些初始化操作。

具体示例:

  1. 基础监听示例:
@Component
public class StartupListener implements ApplicationListener<ApplicationStartedEvent> {
    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        // 应用启动后的初始化操作
        System.out.println("应用已启动,可以执行初始化操作");
    }
}
  1. 常见使用场景:
// 1. 缓存预热
@Component
public class CacheWarmUpListener implements ApplicationListener<ApplicationStartedEvent> {
    @Autowired
    private ProductService productService;
    
    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        // 启动时预加载热门商品到缓存
        List<Product> hotProducts = productService.getHotProducts();
        cacheService.warmUp(hotProducts);
    }
}

// 2. 系统状态检查
@Component
public class SystemCheckListener implements ApplicationListener<ApplicationStartedEvent> {
    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        // 检查必要的外部系统连接
        checkDatabaseConnection();
        checkRedisConnection();
        checkExternalAPIs();
    }
}

// 3. 初始化数据
@Component
public class DataInitListener implements ApplicationListener<ApplicationStartedEvent> {
    @Autowired
    private UserService userService;
    
    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        // 检查并初始化管理员账号
        if (!userService.hasAdminUser()) {
            userService.initializeAdminUser();
        }
    }
}

// 4. 启动定时任务
@Component
public class SchedulerListener implements ApplicationListener<ApplicationStartedEvent> {
    @Autowired
    private TaskScheduler scheduler;
    
    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        // 启动定时任务
        scheduler.scheduleAtFixedRate(
            () -> System.out.println("执行定时任务"), 
            Duration.ofMinutes(5)
        );
    }
}

// 5. 记录启动日志
@Component
public class StartupLoggingListener implements ApplicationListener<ApplicationStartedEvent> {
    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        // 记录启动信息
        log.info("应用启动完成,启动时间:{}", System.currentTimeMillis());
        log.info("系统内存使用情况:{}", Runtime.getRuntime().totalMemory());
    }
}
  1. 使用注解方式监听:
@Component
public class AnnotationStartupListener {
    
    @EventListener(ApplicationStartedEvent.class)
    public void onApplicationEvent() {
        // 处理启动事件
    }
}

主要作用:

  1. 提供应用启动完成的确切时间点
  2. 允许执行一些初始化操作
  3. 进行系统健康检查
  4. 预热缓存或加载数据
  5. 启动后台任务
  6. 记录启动相关的统计信息

优点:

  • 确保在应用完全启动后执行
  • 可以访问所有已初始化的Spring组件
  • 支持多个监听器,可以分模块处理
  • 有明确的执行顺序
  • 可以处理启动失败的情况

这个事件的触发标志着应用已经完全启动,所有的核心组件都已经初始化完成,可以开始处理业务请求了。

7.执行CommandLineRunnerApplicationRunner

CommandLineRunnerApplicationRunner Spring Boot提供的两个接口,用于在应用启动完成后执行一些初始化代码。它们的执行时机比ApplicationStartedEvent更晚,是真正的最后一步。

  1. CommandLineRunner示例:
@Component
@Order(1)  // 指定执行顺序,数字越小优先级越高
public class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        // 可以直接访问命令行参数
        System.out.println("CommandLineRunner执行,参数:" + Arrays.toString(args));
    }
}
  1. ApplicationRunner示例:
@Component
@Order(2)
public class MyApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 可以获取更多的应用参数信息
        System.out.println("选项参数:" + args.getOptionNames());
        System.out.println("非选项参数:" + args.getNonOptionArgs());
        System.out.println("原始参数:" + Arrays.toString(args.getSourceArgs()));
    }
}
  1. 常见使用场景:
// 1. 数据初始化
@Component
public class DataInitializationRunner implements CommandLineRunner {
    @Autowired
    private UserService userService;
    
    @Override
    public void run(String... args) throws Exception {
        // 初始化基础数据
        if (userService.count() == 0) {
            userService.initializeDefaultUsers();
        }
    }
}

// 2. 配置检查
@Component
public class ConfigurationValidationRunner implements ApplicationRunner {
    @Autowired
    private Environment env;
    
    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 验证必要的配置项
        validateDatabaseConfig();
        validateRedisConfig();
        validateApiKeys();
    }
}

// 3. 缓存预热
@Component
public class CacheWarmupRunner implements CommandLineRunner {
    @Autowired
    private ProductService productService;
    
    @Override
    public void run(String... args) throws Exception {
        // 预热缓存
        productService.warmupCache();
    }
}

// 4. 异步任务启动
@Component
public class AsyncTaskRunner implements CommandLineRunner {
    @Autowired
    private TaskExecutor taskExecutor;
    
    @Override
    public void run(String... args) throws Exception {
        taskExecutor.execute(() -> {
            // 执行耗时的初始化任务
            performLongInitialization();
        });
    }
}

// 5. 条件执行
@Component
public class ConditionalRunner implements CommandLineRunner {
    @Value("${app.initialization-required:false}")
    private boolean initializationRequired;
    
    @Override
    public void run(String... args) throws Exception {
        if (initializationRequired) {
            // 执行初始化
            performInitialization();
        }
    }
}
  1. 组合多个Runner:
@Configuration
public class RunnerConfiguration {
    
    @Bean
    public CommandLineRunner compositeRunner(
            DataInitializationRunner dataRunner,
            CacheWarmupRunner cacheRunner) {
        return args -> {
            // 按顺序执行多个初始化任务
            dataRunner.run(args);
            cacheRunner.run(args);
        };
    }
}
  1. 异常处理:
@Component
public class SafeRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        try {
            // 执行可能抛出异常的初始化代码
            riskyInitialization();
        } catch (Exception e) {
            // 记录错误但不中断应用启动
            log.error("初始化失败", e);
        }
    }
}

主要特点:

  1. CommandLineRunner

    • 直接接收命令行参数
    • 接口更简单
  2. ApplicationRunner

    • 提供更多的参数解析功能
    • 可以区分选项参数和非选项参数

这个阶段是应用启动的最后一步,适合执行一些初始化操作,但要注意不要影响应用的正常启动。

8.发布Ready 事件,应用启动完成

ApplicationReadyEventSpring Boot 应用启动的最后一个事件,标志着应用已经完全准备好处理请求了。这是所有初始化完成后的最终状态。

详细解释:

  1. 基础监听示例:
@Component
public class ReadyEventListener implements ApplicationListener<ApplicationReadyEvent> {
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        log.info("应用已完全准备就绪!");
    }
}
  1. 常见使用场景:
// 1. 应用状态通知
@Component
public class ApplicationStatusNotifier implements ApplicationListener<ApplicationReadyEvent> {
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        // 通知监控系统应用已就绪
        notifyMonitoringSystem("APPLICATION_READY");
        
        // 更新应用状态
        updateApplicationStatus("RUNNING");
    }
}

// 2. 启动完成日志记录
@Component
public class StartupMetricsLogger implements ApplicationListener<ApplicationReadyEvent> {
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        // 记录启动耗时
        long startupTime = System.currentTimeMillis() - event.getTimestamp();
        
        // 记录系统信息
        Runtime runtime = Runtime.getRuntime();
        log.info("应用启动完成!启动耗时: {}ms", startupTime);
        log.info("内存使用: {}/{} MB", 
            (runtime.totalMemory() - runtime.freeMemory()) / 1048576,
            runtime.totalMemory() / 1048576);
    }
}

// 3. 健康检查
@Component
public class HealthCheckRunner implements ApplicationListener<ApplicationReadyEvent> {
    @Autowired
    private HealthIndicator healthIndicator;
    
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        Health health = healthIndicator.health();
        if (health.getStatus() == Status.UP) {
            log.info("应用健康检查通过");
        } else {
            log.warn("应用健康检查未通过: {}", health.getDetails());
        }
    }
}

// 4. 外部系统集成
@Component
public class ServiceRegistrationListener implements ApplicationListener<ApplicationReadyEvent> {
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        // 注册到服务发现系统(如Eureka、Consul)
        registerWithDiscoveryService();
        
        // 初始化与外部系统的连接
        initializeExternalConnections();
    }
}

// 5. 性能监控启动
@Component
public class MetricsCollectorStarter implements ApplicationListener<ApplicationReadyEvent> {
    @Autowired
    private MetricsCollector metricsCollector;
    
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        // 启动性能指标收集
        metricsCollector.startCollection();
    }
}
  1. 使用注解方式:
@Component
public class ReadyEventHandler {
    
    @EventListener(ApplicationReadyEvent.class)
    public void handleReadyEvent() {
        // 处理就绪事件
        log.info("应用就绪事件处理");
    }
}
  1. 结合异步处理:
@Component
public class AsyncReadyEventHandler {
    
    @Async
    @EventListener(ApplicationReadyEvent.class)
    public void handleReadyEventAsynchronously() {
        // 异步处理耗时操作
        performTimeConsumingTasks();
    }
}

主要作用:

  1. 标志应用完全启动完成
  2. 提供最后的初始化机会
  3. 适合执行外部系统集成
  4. 收集和报告启动指标
  5. 进行最终的健康检查

与其他事件的区别:

  • ApplicationStartedEvent:基础启动完成
  • ApplicationReadyEvent:完全准备就绪
  • 建议将核心初始化放在Started事件
  • 将非关键操作放在Ready事件

使用建议:

  1. 避免在此阶段执行重量级操作
  2. 需要时使用异步处理
  3. 主要用于状态通知和监控
  4. 做好日志记录
  5. 处理好异常情况

这个事件标志着:

  • 应用完全启动完成
  • 所有初始化任务执行完毕
  • 可以开始处理外部请求
  • 系统进入正常运行状态

这是Spring Boot启动流程的最后一个步骤,之后应用就进入正常的运行状态了。

Springboot 启动日志分析


2025-01-25 16:09:22.359  INFO 40940 --- [           main] c.y.bloomfilter.BloomFilterApplication   : Starting BloomFilterApplication using Java 1.8.0_402 on xiaoxinpro2022 with PID 40940 (D:\B_IDEA\testE_09\verifyRedisCache\BloomFilter\target\classes started by 86180 in D:\B_IDEA\testE_09\verifyRedisCache)
阶段 1 和 2:应用从main()方法启动(阶段1),并创建SpringApplication对象(阶段2)。日志表明应用开始启动,推断应用类型和主类。

2025-01-25 16:09:22.362  INFO 40940 --- [           main] c.y.bloomfilter.BloomFilterApplication   : No active profile set, falling back to 1 default profile: "default"
阶段 3:准备环境时加载配置文件,发现未激活任何配置文件,回退到默认配置。

2025-01-25 16:09:23.960  INFO 40940 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode
创建ApplicationContext时处理Spring Data配置,检测到多个模块并进入严格仓库配置模式。

2025-01-25 16:09:23.967  INFO 40940 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode.
阶段 4:继续加载ApplicationContext,初始化Spring Data Redis仓库。

2025-01-25 16:09:24.032  INFO 40940 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 19 ms. Found 0 Redis repository interfaces.
阶段 4:完成Spring Data仓库的扫描(此处未找到Redis仓库接口)。

2025-01-25 16:09:25.571  INFO 40940 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
阶段 5:在刷新ApplicationContext时启动嵌入式Tomcat服务器。

2025-01-25 16:09:25.604  INFO 40940 --- [           main] 
o.apache.catalina.core.StandardService   : Starting service [Tomcat]
阶段 5:Tomcat服务启动,属于嵌入式服务器初始化的一部分。

2025-01-25 16:09:25.604  INFO 40940 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.65]

2025-01-25 16:09:25.857  INFO 40940 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
阶段 4:初始化Spring的嵌入式Web应用上下文(ApplicationContext刷新阶段的一部分)。

2025-01-25 16:09:25.857  INFO 40940 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 3392 ms
阶段 4:ApplicationContext初始化完成,Bean定义加载完毕。

2025-01-25 16:09:27.791  INFO 40940 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
阶段 4:Hikari连接池初始化,属于Bean的创建和依赖注入阶段。

2025-01-25 16:09:32.033  INFO 40940 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
阶段 4:Hikari连接池启动完成,Bean初始化结束。

2025-01-25 16:09:32.513  INFO 40940 --- [           main] c.y.b.service.Impl.UserServiceImpl       : 布隆过滤器初始化完成
阶段 4:在Bean初始化阶段完成(例如,通过@PostConstruct或@Bean初始化方法),属于上下文刷新的一部分。


2025-01-25 16:09:33.374  INFO 40940 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
阶段 5:嵌入式Tomcat服务器完全启动,端口和上下文路径就绪。


2025-01-25 16:09:33.392  INFO 40940 --- [           main] c.y.bloomfilter.BloomFilterApplication   : Started BloomFilterApplication in 11.851 seconds (JVM running for 18.294)
```阶段 8:应用启动完成,发布ApplicationReadyEvent,进入运行状态。

http://www.kler.cn/a/519902.html

相关文章:

  • 验证二叉搜索树(力扣98)
  • tmp记录
  • 【图文详解】lnmp架构搭建Discuz论坛
  • 一文了解二叉树的基本概念
  • 矩阵快速幂
  • python深入SQLAlchemy使用详解
  • 左右互博02-unidbg主动调用外层so函数
  • 【MQ】RabbitMq的可靠性保证
  • dmfldr实战
  • 云计算架构学习之LNMP架构部署、架构拆分、负载均衡-会话保持
  • 从传统桌面应用到现代Web前端开发:技术对比与高效迁移指南20250122
  • 【Rust自学】14.4. 发布crate到crates.io
  • k8s官方文档的阅读笔记
  • 超融合服务器怎么优化数据管理?
  • 0.91英寸OLED显示屏一种具有小尺寸、高分辨率、低功耗特性的显示器件
  • css粘性定位超出指定宽度失效问题
  • JAVA(SpringBoot)集成Kafka实现消息发送和接收。
  • 深度学习|表示学习|卷积神经网络|由参数共享引出的特征图|08
  • ue5 运行时大纲视图中的数据获取方法
  • Unity|小游戏复刻|见缝插针2(C#)
  • 牛批,吾爱出品
  • 如何实现滑动开关功能
  • 生数科技携手央视新闻《文博日历》,推动AI视频技术的创新应用
  • 今天也是记录小程序进展的一天(破晓时8)
  • 业务对象和对象的区别
  • 1905电影网中国地区电影数据分析(二) - 数据分析与可视化