类路径上有多个 ApplicationRunner,如何让 SpringApplication.run() 只运行一个

And*_*cer 2 spring spring-boot

上下文:我有一个带有一些实用程序的项目来执行数据修复等操作。每个实用程序都是一个 Java 应用程序,即带有main()方法的类。我想将它们定义为 Spring Boot 应用程序,以便我可以使用ApplicationRunnerApplicationArguments工具。Spring 配置是通过共享配置类中的注释定义的。我在下面放了一个这个设置的最小例子。

期望:如果我调用SpringApplication.run(SomeClass.class, args)where SomeClassis an ApplicationRunner,它会run()在该类上运行,而不是在应用程序上下文中的任何其他类上运行。

实际发生的事情:它调用ApplicationRunners上下文中的所有内容。

为什么?我理解的SpringApplication.run(Class, String[])意思是“运行此类”,而它似乎意味着“从此类加载应用程序上下文并运行您可以在其中找到的任何内容”。我应该如何修复它以仅运行 1 个类?我不介意我的其他应用程序类是否不在应用程序上下文中,因为我需要的所有配置都在共享配置类中。但我不想根据我需要运行的类来编辑代码(例如添加或删除注释)。

最小的例子:

一个 Spring 配置类(共享):

package com.stackoverflow.example;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ExampleSpringConfig {
  /** Some bean - just here to check that beans from this config are injected */
  @Bean public FooService fooService () {
    return new FooService();
  }
}
Run Code Online (Sandbox Code Playgroud)

两个应用类

package com.stackoverflow.example;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.annotation.Resource;

@SpringBootApplication
public class SomethingJob implements ApplicationRunner {
  @Resource private FooService fooService;

  public void run(ApplicationArguments args) throws Exception {
    System.out.println("Doing something"); // do things with FooService here
  }

  public static void main(String[] args) {
    SpringApplication.run(SomethingJob.class, args);
  }
}
Run Code Online (Sandbox Code Playgroud)

另一个是相同的,只是它打印“做其他事情”。

输出:

[Spring Boot startup logs...]
Doing something else
Doing something
[Spring Boot shutdown logs...]
Run Code Online (Sandbox Code Playgroud)

afa*_*dge 5

首先,只应使用@SpringBootApplication 注释一个类。正如您在回答中注意到的那样,这定义了外部“主要”入口点。ApplicationRunner为了清晰和概念分离,我建议这是一个与您的课程不同的课程。

为了只让一些但不是所有的跑步者运行,我已经通过解析参数并快速退出不应该被调用的跑步者来做到这一点。例如

package com.stackoverflow.example;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.annotation.Resource;

@Component
public class SomethingJob implements ApplicationRunner {
  @Resource private FooService fooService;

  public void run(ApplicationArguments args) throws Exception {
    if (!args.containsOption("something")) return

    System.out.println("Doing something"); // do things with FooService here
  }

}
Run Code Online (Sandbox Code Playgroud)

这样你就可以做java -jar myjar.jar --somethingjava -jar myjar.jar --something-else取决于你想运行哪一个。