2016-03-17 2 views
2

Я пытаюсь выяснить, как создать автономное приложение Spring Boot. Разумеется, для того, чтобы вещи были автоуведомлены, требуется исходная начальная точка. Если я просто попробую Autowire класс для запуска задания, он равен нулю, даже если я сделаю его статическим.Создать автономное приложение для загрузки Spring

Есть ли способ использовать 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 (обслуживания) класс имеет нестатическое SshSessionService проводное в него. SshSession (Service), наконец, просто имеет конструктор no-arg.

@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

Autowiring on static fields не работает. Если вы хотите запустить метод при запуске, создайте компонент, который реализует интерфейс CommandLineRunner или ApplicationRunner. Бобы, которые реализуют эти интерфейсы, автоматически запускаются Spring Boot, как только приложение будет готово. – dunni

+0

Dunni is right, @JohnnyO –

ответ

2

Несколько различных решений приходит на ум:

Если вы взгляните на метод 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(); 
    } 
} 

Другим решением является использование @PostConstruct аннотации для send() метода:

@Service("jobRunnerService") 
public class JobRunner implements JobRunnerService { 

    @PostConstruct 
    public void send() { ... } 
} 

Однако в вашем случае, я бы реализовать интерфейс ApplicationRunner, либо в качестве отдельного бин, который autowires в 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(); 
    } 
} 
+0

OMG @matsev Я использовал последнее предложение внедрения ... Отлично спасибо! – JohnnyO

0

Вы не указали код для JobRunnerService, но я предполагаю, что у него есть конструктор по умолчанию и что он добавлен в аннотацию @Component для Spring, чтобы понять его как фасоль, прежде чем вы сможете его автоустанавливать. ваш job является недействительным, вероятно, потому что это не в состоянии найти autowired боб для JobRunnerService и это, вероятно, потому, что у вас нет идентификатора для Spring для сканирования и создания боба типа JobRunnerService

0

Вы можете использовать @Services или @Component к JobRunnerService класс затем добавить аннотацию @ComponentScan("package of JobRunnerService") ниже @SpringBootApplication, смотрите по этой ссылке:

How to scan multiple paths using the @ComponentScan annotation?

+0

Что-то принципиально неправильно в том, что я делаю ... поэтому компоненты не могут работать ... Я просто не знаю, как это сделать. – JohnnyO

+0

Dunni прав, автоустановка на статическом поле не будет работать. Я этого не заметил. –

0

Вам нужно несколько шагов, чтобы получить автономное приложение работы:

  1. A класс с main() метод.
  2. A @SpringBootApplication аннотация для вашего основного класса.
  3. И вызов метода SpringApplication.run().

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 для настройки каталогов, которые должны использоваться для сканирования компонентов.

Пример скопирован из пункта @SpringBootApplication в справочные документы Spring Boot (см. Ссылку выше). Если вы хотите быстро начать свой проект, в комплекте с скриптами сборки (Maven или Gradle), зависимостью и т.д., вы можете создать скелет проекта с использованием Spring Initializr

+0

У меня есть это уже, но что может пойти ниже вызова вызова в основном методе, чтобы ссылаться на следующий вызов в моем случае job.send(), если вы посмотрите на мой код выше, вы увидите, что это проблема с инициализацией bean-компонентов, которые являются @Services ... – JohnnyO

0

Я пытаюсь запустить как нить/исполняемым в настоящее время, как указано в документе Spring 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.springframew ork.beans.factory.NoSuchBeanDefinitionException: Нет квалификационного компонента типа [org.springframework.core.task.TaskExecutor], найденного для зависимостей

Как я могу получить импортированный lib, который будет принят в качестве компонента TaskExecutor?

Смежные вопросы