【问题标题】:How does a Spring Boot console based application work?基于 Spring Boot 控制台的应用程序如何工作?
【发布时间】:2015-03-27 19:26:43
【问题描述】:

如果我正在开发一个相当简单的基于 Spring Boot 控制台的应用程序,我不确定主要执行代码的位置。我应该把它放在 public static void main(String[] args) 方法中,还是让主应用程序类实现 CommandLineRunner 接口并将代码放在 run(String... args) 方法?

我将使用一个示例作为上下文。假设我有以下 [基本] 应用程序(编码为接口,Spring 风格):

Application.java

public class Application {

  @Autowired
  private GreeterService greeterService;

  public static void main(String[] args) {
    // ******
    // *** Where do I place the following line of code
    // *** in a Spring Boot version of this application?
    // ******
    System.out.println(greeterService.greet(args));
  }
}

GreeterService.java(接口)

public interface GreeterService {
  String greet(String[] tokens);
}

GreeterServiceImpl.java(实现类)

@Service
public class GreeterServiceImpl implements GreeterService {
  public String greet(String[] tokens) {

    String defaultMessage = "hello world";

    if (args == null || args.length == 0) {
      return defaultMessage;
    }

    StringBuilder message = new StringBuilder();
    for (String token : tokens) {
      if (token == null) continue;
      message.append(token).append('-');
    }

    return message.length() > 0 ? message.toString() : defaultMessage;
  }
}

Application.java 的等效 Spring Boot 版本大致如下: GreeterServiceImpl.java(实现类)

@EnableAutoConfiguration
public class Application
    // *** Should I bother to implement this interface for this simple app?
    implements CommandLineRunner {

    @Autowired
    private GreeterService greeterService;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        System.out.println(greeterService.greet(args)); // here?
    }

    // Only if I implement the CommandLineRunner interface...
    public void run(String... args) throws Exception {
        System.out.println(greeterService.greet(args)); // or here?
    }
}

【问题讨论】:

  • 使用CommandLineRunner,这就是它的设计目的,您还可以创建它的一个实例并将依赖项注入其中。这在您的第一个场景中会失败,因为您不会注入依赖项或无法从静态方法访问它。
  • @M.Deinum 所以这样的基于控制台的应用程序必须实现 CommandLineRunner 接口作为一般经验法则?这为我提供了足够的清晰度,因为即使是文档也没有关注这一点(可能是因为它对大多数人来说是隐含的!)。
  • 那么你最好创建一个实现这个接口的bean(而不是你的Application类)。它与关注点分离(启动应用程序并执行逻辑)有关。
  • 你指的是GreeterService [implementation] bean吗?因为我的Application 班级只使用这个服务。所以此时已经存在关注点分离,不是吗?
  • 不,我不是指那个。对于一些阅读,您一直在提到您希望您的 Application 类实现 CommandLineRunner 接口。您可能不希望这样做,而是在单独的课程中这样做。

标签: java console-application spring-boot


【解决方案1】:

你应该有一个标准的加载器:

@SpringBootApplication
public class MyDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyDemoApplication.class, args);
    }
}

并使用@Component 注解实现CommandLineRunner 接口

    @Component
    public class MyRunner implements CommandLineRunner {

       @Override    
       public void run(String... args) throws Exception {

      }
   }

@EnableAutoConfiguration 将执行通常的 SpringBoot 魔术。

更新:

正如@jeton 建议的那样,最新的 Springboot 实现了一个直:

spring.main.web-application-type=none
spring.main.banner-mode=off

docs at 72.2

【讨论】:

  • 为什么你认为这是使用 Spring Boot 实现 CLI 应用程序的正确方法? CommandLineRunnerApplicationRunner 不仅仅用于 CLI 应用程序。另外,当您使用其中任何一个时,Spring 在启动您的应用程序的 main 方法之前执行其各自的 run 方法,正如在您的 CommandLineRunner.run(...) 方法中的代码执行之后出现的日志消息 INFO 6961 --- [ restartedMain] org.behrang.rpn.Main : Started Main in XX.YYY seconds (JVM running for MM.NNN) 所证明的那样。
  • @Behrang 那么正确的做法是什么?
  • @Wesam 不幸的是,据我所知,没有一种优雅的方法可以做到这一点。这是一个可能的解决方案:gist.github.com/behrangsa/6a7f050e7f6d193918ad7e910812fb28
  • @Behrang 这个答案给出了实现这个功能的正确方法。我刚刚建议进行编辑以添加指向官方示例的链接:github.com/spring-projects/spring-boot/tree/v1.4.2.RELEASE/…
  • 在 springboot 2 中是spring.main.web-application-type=none
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-28
  • 2011-05-12
  • 1970-01-01
  • 1970-01-01
  • 2012-09-15
  • 2018-12-06
  • 1970-01-01
相关资源
最近更新 更多