创建Spring启动独立应用程序

时间:2016-03-17 17:29:52

标签: spring-boot

我正在试图弄清楚如何构建一个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作业引用处开始为空。

5 个答案:

答案 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

类型的bean

答案 2 :(得分:0)

您可以将@Services@Component用于JobRunnerService类,然后在@ComponentScan("package of JobRunnerService")下添加注释@SpringBootApplication,请参阅此链接:

How to scan multiple paths using the @ComponentScan annotation?

答案 3 :(得分:0)

您需要几个步骤才能让独立应用运行起来:

  1. 使用main()方法的课程。
  2. 您的主要班级的@SpringBootApplication注释。
  3. 调用SpringApplication.run()方法。
  4. 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组成。换句话说,它可以由后三个注释代替。或者,您可以使用别名scanBasePackagescanBasePackageClasses来自定义应该用于组件扫描的目录。

    该示例是从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?