首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类路径上的多个ApplicationRunners,如何使SpringApplication.run()只运行一个

类路径上的多个ApplicationRunners,如何使SpringApplication.run()只运行一个
EN

Stack Overflow用户
提问于 2016-02-18 10:19:53
回答 2查看 2.9K关注 0票数 2

上下文:我有一个带有一些实用程序的项目,可以做诸如数据修复之类的事情。每个实用程序都是一个Java应用程序,即具有main()方法的类。我想将它们定义为Spring应用程序,以便我可以使用ApplicationRunnerApplicationArguments工具。Spring配置是通过共享配置类中的注释来定义的。下面是这个设置的一个极小的例子。

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

实际发生的情况:它调用上下文中的所有ApplicationRunners

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

最起码的例子:

类(共享):

代码语言:javascript
复制
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();
  }
}

两个应用程序类

代码语言:javascript
复制
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);
  }
}

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

输出:

代码语言:javascript
复制
[Spring Boot startup logs...]
Doing something else
Doing something
[Spring Boot shutdown logs...]
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-03-06 17:19:00

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

为了只运行一些而不是所有的运行程序,我通过解析参数和快速退出不应该调用的运行程序来实现这一点。例如:

代码语言:javascript
复制
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
  }

}

通过这种方式,您可以执行java -jar myjar.jar --somethingjava -jar myjar.jar --something-else,这取决于您想要运行哪一个。

票数 5
EN

Stack Overflow用户

发布于 2016-02-18 10:34:04

我在用最小的例子做实验时找到了一个解决办法。

@SpringBootApplication只是@ComponentScan@EnableAutoConfiguration@Configuration的别名。通过单独应用它们,我发现是@Configuration注释导致了这种行为。如果我只应用另外两个,我就不明白问题了。

我猜这是因为@Configuration的意思是“I是一个配置类,我定义的任何bean都应该在组件扫描期间被拖到上下文中”,尽管这个类没有定义ApplicationRunner,但是它具有相同的效果。因此,如果类路径上有两个这样的bean,它们都会被拖到应用程序上下文中。

如果没有@Configuration,您想要运行的bean仍然会被注册,因为它是通过对run()的调用引用的,但是类路径上的其他ApplicationRunner没有。

这解决了我眼前的问题,确保我在我的应用程序上下文中只有一个ApplicationRunner。但是它并没有回答更广泛的问题,“如果我有几个ApplicationRunner,我如何告诉Spring运行哪一个?”因此,我仍然希望有更完整的答案或对不同方法的建议。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35478679

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档