我正在试图弄清楚如何构建一个Spring Boot独立应用程序。当然,自动装配需要一些初始的上下文起点。如果我只是尝试Autowire一个类来运行一个作业,那么即使我将它设置为静态也是如此。
有没有办法在独立的非Web应用程序中使用Spring @Services?
@SpringBootApplication
public class MyApplication {
@Autowired
private static JobRunnerService job;
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
job.send(); //job is null !
}
}
因此,首先将静态JobRunnerService连接到运行MyApplication的主服务器,JobRunner(Service)类将非静态SshSessionService连接到其中。 SshSession(Service)最终只有一个无参数的构造函数。
@Service("jobRunnerService")
public final class JobRunner implements JobRunnerService{
@Autowired
private SshSessionService ssh;
@Autowired
public JobRunner(SshSessionService ssh){
this.ssh = ssh;
}
public void sendToAgent() { ....
}
@Service("sshSessionService")
public class SshSession implements SshSessionService {
public SshSession() {
}
}
它在JobRunnerService作业引用处开始为空。
答案 0 :(得分:4)
我想到了几种不同的解决方案:
如果您查看SpringApplication.run()方法,您会发现它返回ApplicationContext
。从那里,您可以获取JobRunnerService
,例如
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(MyApplication.class, args);
JobRunnerService job = ctx.getBean(JobRunnerService.class);
job.send();
}
}
另一种解决方案是对send()
方法使用@PostConstruct注释:
@Service("jobRunnerService")
public class JobRunner implements JobRunnerService {
@PostConstruct
public void send() { ... }
}
但是在你的情况下,我会实现ApplicationRunner接口,或者作为一个单独的bean自动装配JobRunnerService
,然后调用它的send()
方法
@Component
public class SendRunner implements ApplicationRunner {
@Autowired
private JobRunnerService job;
@Override
public void run(ApplicationArguments args) {
job.send();
}
}
或让JobRunner
直接实现ApplicationRunner
界面:
@Service("jobRunnerService")
public class JobRunner implements JobRunnerService, ApplicationRunner {
@Override
public void send() { ... }
@Override
public void run(ApplicationArguments args) {
send();
}
}
答案 1 :(得分:0)
您还没有为JobRunnerService
提供代码,但我假设它有一个默认构造函数,并且它由@Component
注释,以便Spring将其计算为bean之前实际上是自动装配它。您的job
为空可能是因为它无法为JobRunnerService
找到自动装配的bean,而这可能是因为您没有Spring的扫描标识符创建JobRunnerService
答案 2 :(得分:0)
您可以将@Services
或@Component
用于JobRunnerService类,然后在@ComponentScan("package of JobRunnerService")
下添加注释@SpringBootApplication
,请参阅此链接:
How to scan multiple paths using the @ComponentScan annotation?
答案 3 :(得分:0)
您需要几个步骤才能让独立应用运行起来:
main()
方法的课程。package com.example.myproject;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
如上所述,@SpringBootApplication
是一个复合注释,由@Configuration
@EnableAutoConfiguration
和@ComponentScan
组成。换句话说,它可以由后三个注释代替。或者,您可以使用别名scanBasePackage或scanBasePackageClasses来自定义应该用于组件扫描的目录。
该示例是从Spring Boot参考文档中的@SpringBootApplication
段落复制而来的(参见上面的链接)。如果您想快速启动项目,完成构建脚本(Maven或Gradle),依赖项等,您可以使用Spring Initializr生成项目框架
答案 4 :(得分:0)
我正试图像Spring文档中提到的那样以Thread / runnable运行3.任务执行和调度..
import org.springframework.core.task.TaskExecutor;
public class TaskExecutorExample {
private class MessagePrinterTask implements Runnable {
private String message;
public MessagePrinterTask(String message) {
this.message = message;
}
public void run() {
System.out.println(message);
}
}
private TaskExecutor taskExecutor;
public TaskExecutorExample(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
public void printMessages() {
for(int i = 0; i < 25; i++) {
taskExecutor.execute(new MessagePrinterTask("Message" + i));
}
}
}
所以在我的情况下,我正在尝试......
@Service("jobRunnerService")
@Component
public class JobRunner implements JobRunnerService, ApplicationRunner{
@Autowired
public TaskExecutor taskExecutor;
@Autowired
private SshSessionService ssh;
private class JobTask implements Runnable{
public void run(){
Boolean success = connectToAgent();
if(success){
log.debug("CONNECTED!!!");
}
}
}
/**
* Construct JobRunner with TaskExecutor
* @param taskExecutor
*/
@Autowired
public JobRunner(TaskExecutor taskExecutor, SshSessionService ssh) {
this.taskExecutor = taskExecutor;
this.ssh = ssh;
}
private Map<String, String> sessionParams;
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public void run(ApplicationArguments args) {
/**
* Starting point of application
*
*/
taskExecutor.execute(new JobTask());
}
刚刚获取org.springframework.beans.factory.NoSuchBeanDefinitionException:找不到类型为[org.springframework.core.task.TaskExecutor]的限定bean用于依赖
如何让导入的lib被接受为TaskExecutor Bean?