上下文:我有一个带有一些实用程序的项目,可以做诸如数据修复之类的事情。每个实用程序都是一个Java应用程序,即具有main()方法的类。我想将它们定义为Spring应用程序,以便我可以使用ApplicationRunner和ApplicationArguments工具。Spring配置是通过共享配置类中的注释来定义的。下面是这个设置的一个极小的例子。
期望:如果我调用SpringApplication.run(SomeClass.class, args) ( SomeClass是ApplicationRunner ),它会在该类上运行run(),而不是在应用程序上下文中的任何其他类上运行run()。
实际发生的情况:它调用上下文中的所有ApplicationRunners。
为什么?我理解SpringApplication.run(Class, String[])的意思是“运行这个类”,而它似乎意味着“从这个类加载一个应用程序上下文,并运行您可以在其中找到的任何东西”。我应该如何修复它,使其只运行一个类?我不介意我的另一个应用程序类不在应用程序上下文中,因为我需要的所有配置都在共享配置类中。但我不想编辑代码(例如添加或删除注释),根据需要运行的类。
最起码的例子:
类(共享):
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();
}
}两个应用程序类
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);
}
}另一个是相同的,除了打印“做其他的事情”。
输出:
[Spring Boot startup logs...]
Doing something else
Doing something
[Spring Boot shutdown logs...]发布于 2017-03-06 17:19:00
首先,只有一个类应该使用@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
}
}通过这种方式,您可以执行java -jar myjar.jar --something或java -jar myjar.jar --something-else,这取决于您想要运行哪一个。
发布于 2016-02-18 10:34:04
我在用最小的例子做实验时找到了一个解决办法。
@SpringBootApplication只是@ComponentScan、@EnableAutoConfiguration和@Configuration的别名。通过单独应用它们,我发现是@Configuration注释导致了这种行为。如果我只应用另外两个,我就不明白问题了。
我猜这是因为@Configuration的意思是“I是一个配置类,我定义的任何bean都应该在组件扫描期间被拖到上下文中”,尽管这个类没有定义ApplicationRunner,但是它具有相同的效果。因此,如果类路径上有两个这样的bean,它们都会被拖到应用程序上下文中。
如果没有@Configuration,您想要运行的bean仍然会被注册,因为它是通过对run()的调用引用的,但是类路径上的其他ApplicationRunner没有。
这解决了我眼前的问题,确保我在我的应用程序上下文中只有一个ApplicationRunner。但是它并没有回答更广泛的问题,“如果我有几个ApplicationRunner,我如何告诉Spring运行哪一个?”因此,我仍然希望有更完整的答案或对不同方法的建议。
https://stackoverflow.com/questions/35478679
复制相似问题