Spring Boot启动后运行代码

时间:2014-12-10 16:12:09

标签: java spring spring-boot

我希望在 spring-boot 应用程序开始监视目录以进行更改后运行代码。

我尝试过运行新线程,但此时尚未设置@Autowired服务。

我能够找到ApplicationPreparedEvent,它会在设置@Autowired注释之前触发。理想情况下,我希望在应用程序准备好处理http请求后触发该事件。

是否有更好的事件要使用,或者在应用程序在 spring-boot 中运行后运行代码的更好方式?

16 个答案:

答案 0 :(得分:200)

就这么简单:

@EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup() {
    System.out.println("hello world, I have just started up");
}

在版本1.5.1.RELEASE

上测试

答案 1 :(得分:88)

尝试:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application extends SpringBootServletInitializer {

    @SuppressWarnings("resource")
    public static void main(final String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);

        context.getBean(Table.class).fillWithTestdata(); // <-- here
    }
}

答案 2 :(得分:82)

您是否尝试过ApplicationReadyEvent?

@Component
public class ApplicationStartup 
implements ApplicationListener<ApplicationReadyEvent> {

  /**
   * This event is executed as late as conceivably possible to indicate that 
   * the application is ready to service requests.
   */
  @Override
  public void onApplicationEvent(final ApplicationReadyEvent event) {

    // here your code ...

    return;
  }
}

代码来自:http://blog.netgloo.com/2014/11/13/run-code-at-spring-boot-startup/

这是documentation提到的关于创业活动的内容:

  

...

     

应用程序事件在应用程序运行时按以下顺序发送:

     

ApplicationStartedEvent在运行开始时发送,但之前发送   除了听众和初始化者的注册之外的任何处理。

     

当要在上下文中使用的环境已知但在上下文之前发送ApplicationEnvironmentPreparedEvent   已创建。

     

ApplicationPreparedEvent在刷新开始之前发送,但是在加载了bean定义之后发送。

     

在刷新之后发送ApplicationReadyEvent并且已经处理了任何相关的回调以指示应用程序已准备好   服务请求。

     

如果启动时发生异常,则会发送ApplicationFailedEvent。

     

...

答案 3 :(得分:77)

为什么不创建一个在初始化时启动监视器的bean,如:

@Component
public class Monitor {
    @Autowired private SomeService service

    @PostConstruct
    public void init(){
        // start your monitoring in here
    }
}

在为bean完成任何自动装配之前,不会调用init方法。

答案 4 :(得分:58)

&#34; Spring Boot&#34;方法是使用CommandLineRunner。只需添加那种类型的豆子就可以了。在Spring 4.1(Boot 1.2)中,还有一个SmartInitializingBean在所有内容初始化后获得回调。还有SmartLifecycle(来自Spring 3)。

答案 5 :(得分:33)

您可以使用ApplicationRunner扩展一个类,覆盖run()方法并在那里添加代码。

import org.springframework.boot.ApplicationRunner;

@Component
public class ServerInitializer implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments applicationArguments) throws Exception {

        //code goes here

    }
}

答案 6 :(得分:18)

ApplicationReadyEvent仅在您要执行的任务不是正确的服务器操作要求时才有用。启动异步任务以监视某些更改是一个很好的例子。

但是,如果您的服务器在任务完成之前处于“未就绪”状态,则最好实施SmartInitializingSingleton,因为您将在 REST端口之前获得回调已打开,您的服务器已开放营业。

不要试图将@PostConstruct用于只应该发生过一次的任务。当你注意到它被多次调用时,你会得到一个粗鲁的惊喜......

答案 7 :(得分:11)

在春天使用SmartInitializingSingleton bean&gt; 4.1

@Bean
public SmartInitializingSingleton importProcessor() {
    return () -> {
        doStuff();
    };

}

作为替代方案,可以使用CommandLineRunner实现@PostConstruct bean或使用{{1}}注释bean方法。

答案 8 :(得分:4)

为Dave Syer的答案提供一个例子,它就像一个魅力:

@Component
public class CommandLineAppStartupRunner implements CommandLineRunner {
    private static final Logger logger = LoggerFactory.getLogger(CommandLineAppStartupRunner.class);

    @Override
    public void run(String...args) throws Exception {
        logger.info("Application started with command-line arguments: {} . \n To kill this application, press Ctrl + C.", Arrays.toString(args));
    }
}

答案 9 :(得分:3)

尝试这一操作,它将在应用程序上下文完全启动后运行您的代码。

 @Component
public class OnStartServer implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent arg0) {
                // EXECUTE YOUR CODE HERE 
    }
}

答案 10 :(得分:2)

只需为Spring Boot应用程序实现CommandLineRunner。 您需要实现run方法,

public classs SpringBootApplication implements CommandLineRunner{

    @Override
        public void run(String... arg0) throws Exception {
        // write your logic here 

        }
}

答案 11 :(得分:2)

Spring Boot应用程序启动后执行代码块的最佳方法是使用PostConstruct批注。或者,也可以使用命令行运行器。

1。使用PostConstruct批注

@Configuration
public class InitialDataConfiguration {

    @PostConstruct
    public void postConstruct() {
        System.out.println("Started after Spring boot application !");
    }

}

2。使用命令行流道bean

@Configuration
public class InitialDataConfiguration {

    @Bean
    CommandLineRunner runner() {
        return args -> {
            System.out.println("CommandLineRunner running in the UnsplashApplication class...");
        };
    }
}

答案 12 :(得分:0)

我非常喜欢@cahen(https://stackoverflow.com/a/44923402/9122660)使用@EventListener fun doSomethingAfterStartup(event: ApplicationReadyEvent) { System.out.println("hello world, I have just started up"); } 注释的建议,因为它非常干净。不幸的是,我无法在Spring + Kotlin设置中使用它。对于Kotlin起作用的是将类添加为方法参数:

K.clear_session()

答案 13 :(得分:0)

使用CommandLineRunner或ApplicationRunner的最佳方法 两者之间的唯一区别是run()方法 CommandLineRunner接受字符串数组,ApplicationRunner接受ApplicationArugument。

答案 14 :(得分:0)

您可以使用@Component

\r

答案 15 :(得分:0)

您有多种选择:

使用 CommandLineRunnerApplicationRunner 作为 Bean 定义:

Spring Boot 在应用程序启动过程结束时执行这些。在大多数情况下,CommandLineRunner 将完成这项工作。以下是使用 Java 8 实现 CommandLineRunner 的示例:

@Bean
public CommandLineRunner commandLineRunner() {
   return (args) -> System.out.println("Hello World");
}

请注意,args 是参数的字符串数组。您还可以提供此接口的实现并将其定义为 Spring 组件:

@Component
public class MyCommandLineRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("Hello World");
    }
}

如果您需要更好的参数管理,您可以使用 ApplicationRunner。 ApplicationRunner 采用具有增强的参数管理选项的 ApplicationArguments 实例。

您还可以使用 Spring 的 CommandLineRunner 注释对 ApplicationRunner@Order bean 进行排序:

 @Bean
 @Order(1)
 public CommandLineRunner commandLineRunner() {
    return (args) -> System.out.println("Hello World, Order 1");
 }

 @Bean
 @Order(2)
 public CommandLineRunner commandLineRunner() {
    return (args) -> System.out.println("Hello World, Order 2");
 }

使用 Spring Boot 的 ContextRefreshedEvent:

Spring Boot 在启动时发布几个事件。这些事件表明应用程序启动过程中的一个阶段已完成。您可以收听 ContextRefreshedEvent 并执行自定义代码:

@EventListener(ContextRefreshedEvent.class)
public void execute() {
    if(alreadyDone) {
      return;
    }
    System.out.println("hello world");
} 

ContextRefreshedEvent 已发布多次。因此,确保检查代码执行是否已经完成。