面试题:如何在 SpringBoot 启动时执行特定代码?有哪些方式?

在 Spring Boot 中,有多种方式可以在应用启动时执行特定代码。以下是常见的几种方式:


1. 使用 CommandLineRunner 接口

  • CommandLineRunner 是 Spring Boot 提供的一个接口,实现该接口的 run 方法可以在应用启动后执行特定代码。
  • 如果有多个 CommandLineRunner,可以通过 @Order 注解或实现 Ordered 接口来指定执行顺序。
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("应用启动时执行特定代码 - CommandLineRunner");
}
}
   import org.springframework.boot.CommandLineRunner;
   import org.springframework.stereotype.Component;

   @Component
   public class MyCommandLineRunner implements CommandLineRunner {
       @Override
       public void run(String... args) throws Exception {
           System.out.println("应用启动时执行特定代码 - CommandLineRunner");
       }
   }
import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @Component public class MyCommandLineRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("应用启动时执行特定代码 - CommandLineRunner"); } }

2. 使用 ApplicationRunner 接口

  • ApplicationRunnerCommandLineRunner 类似,但它的 run 方法接收的是 ApplicationArguments 对象,可以更方便地处理命令行参数。
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("应用启动时执行特定代码 - ApplicationRunner");
}
}
   import org.springframework.boot.ApplicationArguments;
   import org.springframework.boot.ApplicationRunner;
   import org.springframework.stereotype.Component;

   @Component
   public class MyApplicationRunner implements ApplicationRunner {
       @Override
       public void run(ApplicationArguments args) throws Exception {
           System.out.println("应用启动时执行特定代码 - ApplicationRunner");
       }
   }
import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; @Component public class MyApplicationRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { System.out.println("应用启动时执行特定代码 - ApplicationRunner"); } }

3. 使用 @PostConstruct 注解

  • @PostConstruct 是 JSR-250 提供的注解,标记在方法上后,Spring 会在依赖注入完成后调用该方法。
  • 这种方式适用于在 Bean 初始化时执行代码。
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;
@Component
public class MyPostConstructBean {
@PostConstruct
public void init() {
System.out.println("Bean 初始化时执行特定代码 - @PostConstruct");
}
}
   import javax.annotation.PostConstruct;
   import org.springframework.stereotype.Component;

   @Component
   public class MyPostConstructBean {
       @PostConstruct
       public void init() {
           System.out.println("Bean 初始化时执行特定代码 - @PostConstruct");
       }
   }
import javax.annotation.PostConstruct; import org.springframework.stereotype.Component; @Component public class MyPostConstructBean { @PostConstruct public void init() { System.out.println("Bean 初始化时执行特定代码 - @PostConstruct"); } }

4. 使用 ApplicationListener 监听 ApplicationReadyEvent 事件

  • Spring Boot 提供了多种应用事件,可以通过实现 ApplicationListener 接口来监听这些事件。
  • ApplicationReadyEvent 事件表示应用已完全启动,可以安全地执行代码。
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class MyApplicationListener implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
System.out.println("应用完全启动后执行特定代码 - ApplicationListener");
}
}
   import org.springframework.boot.context.event.ApplicationReadyEvent;
   import org.springframework.context.ApplicationListener;
   import org.springframework.stereotype.Component;

   @Component
   public class MyApplicationListener implements ApplicationListener<ApplicationReadyEvent> {
       @Override
       public void onApplicationEvent(ApplicationReadyEvent event) {
           System.out.println("应用完全启动后执行特定代码 - ApplicationListener");
       }
   }
import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; @Component public class MyApplicationListener implements ApplicationListener<ApplicationReadyEvent> { @Override public void onApplicationEvent(ApplicationReadyEvent event) { System.out.println("应用完全启动后执行特定代码 - ApplicationListener"); } }

5. 使用 @EventListener 注解

  • ApplicationListener 类似,但可以使用 @EventListener 注解来简化代码。
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class MyEventListener {
@EventListener(ApplicationReadyEvent.class)
public void onApplicationReady() {
System.out.println("应用完全启动后执行特定代码 - @EventListener");
}
}
   import org.springframework.boot.context.event.ApplicationReadyEvent;
   import org.springframework.context.event.EventListener;
   import org.springframework.stereotype.Component;

   @Component
   public class MyEventListener {
       @EventListener(ApplicationReadyEvent.class)
       public void onApplicationReady() {
           System.out.println("应用完全启动后执行特定代码 - @EventListener");
       }
   }
import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; @Component public class MyEventListener { @EventListener(ApplicationReadyEvent.class) public void onApplicationReady() { System.out.println("应用完全启动后执行特定代码 - @EventListener"); } }

6. @Bean 方法中直接编写初始化逻辑

  • 在配置类中定义 @Bean 方法时,可以直接在方法体中编写初始化逻辑。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfig {
@Bean
public String initBean() {
System.out.println("Bean 初始化时执行特定代码 - @Bean");
return "Initialized Bean";
}
}
   import org.springframework.context.annotation.Bean;
   import org.springframework.context.annotation.Configuration;

   @Configuration
   public class MyConfig {
       @Bean
       public String initBean() {
           System.out.println("Bean 初始化时执行特定代码 - @Bean");
           return "Initialized Bean";
       }
   }
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyConfig { @Bean public String initBean() { System.out.println("Bean 初始化时执行特定代码 - @Bean"); return "Initialized Bean"; } }

7. 使用 SpringApplicationrun 方法

  • main 方法中,可以在 SpringApplication.run() 之后直接编写代码。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
System.out.println("应用启动后执行特定代码 - main 方法");
}
}
   import org.springframework.boot.SpringApplication;
   import org.springframework.boot.autoconfigure.SpringBootApplication;

   @SpringBootApplication
   public class MyApplication {
       public static void main(String[] args) {
           SpringApplication.run(MyApplication.class, args);
           System.out.println("应用启动后执行特定代码 - main 方法");
       }
   }
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); System.out.println("应用启动后执行特定代码 - main 方法"); } }

8. 使用 InitializingBean 接口

  • 实现 InitializingBean 接口的 afterPropertiesSet 方法,可以在 Bean 初始化时执行代码。
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@Component
public class MyInitializingBean implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Bean 初始化时执行特定代码 - InitializingBean");
}
}
   import org.springframework.beans.factory.InitializingBean;
   import org.springframework.stereotype.Component;

   @Component
   public class MyInitializingBean implements InitializingBean {
       @Override
       public void afterPropertiesSet() throws Exception {
           System.out.println("Bean 初始化时执行特定代码 - InitializingBean");
       }
   }
import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component; @Component public class MyInitializingBean implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { System.out.println("Bean 初始化时执行特定代码 - InitializingBean"); } }

9. 使用 @Configuration 类的静态代码块

  • 在配置类中使用静态代码块,可以在类加载时执行代码。
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyStaticConfig {
static {
System.out.println("配置类加载时执行特定代码 - 静态代码块");
}
}
   import org.springframework.context.annotation.Configuration;

   @Configuration
   public class MyStaticConfig {
       static {
           System.out.println("配置类加载时执行特定代码 - 静态代码块");
       }
   }
import org.springframework.context.annotation.Configuration; @Configuration public class MyStaticConfig { static { System.out.println("配置类加载时执行特定代码 - 静态代码块"); } }

总结

  • 推荐方式CommandLineRunnerApplicationRunner 是最常用的方式,适合在应用启动后执行初始化逻辑。
  • 灵活选择:根据具体需求选择合适的方式,例如:
    • 如果需要处理命令行参数,使用 ApplicationRunner
    • 如果需要在 Bean 初始化时执行代码,使用 @PostConstructInitializingBean
    • 如果需要监听应用事件,使用 ApplicationListener@EventListener

这些方式都可以在 Spring Boot 启动时执行特定代码,选择合适的方式可以提高代码的可读性和可维护性。

THE END
点赞10 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容