Как вызвать службу из основного приложения, вызывающего Spring Boot?

Я создаю приложение Spring Boot, которое будет вызываться из командной строки. Я передам приложению некоторые параметры, но у меня проблемы с вызовом службы из этого класса:

@SpringBootApplication
public class App{

    public static void main(String[] args) {

        SpringApplication.run(App.class, args);

        App app = new App();
        app.myMethod();    
    }

    @Autowired
    private MyService myService;

    private void myMethod(){
        myService.save();
    }
}

Я пытаюсь вызвать метод из основного, но получаю сообщение об ошибке:

Exception in thread "main" java.lang.NullPointerException
at com.ef.Parser.App.myMethod(Application.java:26)
at com.ef.Parser.App.main(Application.java:18)

экземпляр, который вы создаете в основном, не совпадает с экземпляром Springboot; вы можете удалить эти строки в main и вместо этого добавить аннотацию @PostContruct поверх myMethod ()

guido 06.04.2018 20:30
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
23
1
39 712
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

вы можете создать класс, реализующий CommandLineRunner, и он будет вызываться после запуска приложения.

@Component
public class CommandLineAppStartupRunner implements CommandLineRunner {
    @Autowired
    private MyService myService;

    @Override
    public void run(String...args) throws Exception {
       myService.save();

    }
}

вы можете получить более подробную информацию об этом здесь

Работал! Спасибо

Roland 08.04.2018 02:32

Есть ли способ вызвать метод с терминала? Я имею в виду метод save ().

ken4ward 26.10.2019 14:51

@ ken4ward, в основном нет прямого способа вызвать определенную функцию внутри всего приложения без вызова всего приложения ... вы можете обойти это с помощью многих функций Spring, таких как профили, условные классы и переменные env, что такое ваш вариант использования именно?

shahaf 26.10.2019 15:41

Используя ключевое слово new для создания экземпляра класса App, Spring не может об этом узнать.

Это также излишне, поскольку Spring автоматически создает экземпляр bean-компонента этого класса с помощью механизма, называемого сканированием компонентов.

Мне нравится решение CommandLineRunner.

Что вы также можете сделать, так это получить ApplicationContext, найти компонент и затем вызвать метод.

Вы можете ввести ApplicationContext, позволив вашему классу App реализовать ApplicationContextAware, переопределить метод установки и сохранить контекст в статической переменной, к которой вы можете получить доступ из вашего основного метода.

Затем вы можете использовать его для получения правильного экземпляра App.

App myApp = (App) applicationContext.getBean(App.class);
myApp.myMethod()

Обратите внимание, что прямой доступ к ApplicationContext нарушает весь принцип внедрения зависимостей, но иногда у вас нет особого выбора.

В Spring Boot 2.x вы можете просто запустить приложение методом SpringApplication.run и работать с возвращенным ApplicationContext. Полный пример ниже:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import java.util.Arrays;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        ApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);
        SomeService service = applicationContext.getBean(SomeService.class);
        service.doSth(args);
    }
}

@Service
class SomeService {

    public void doSth(String[] args){
        System.out.println(Arrays.toString(args));
    }
}

спаси мою ночь :)

ahmednabil88 15.05.2020 23:01

Проблема с вашим кодом в том, что вы не искали bean-компонент applicationContext для службы, которую используете. У меня был аналогичный вариант использования, чтобы вызвать службу функций при запуске приложения. Инициализация нескольких bean-компонентов applicationContext для служб, а затем выполнение вызываемого метода работает нормально! Код ниже:

public static void main(String[] args) {
    ApplicationContext applicationContext = SpringApplication.run(UamRbacApplication.class, args);
    AccessChangeSchedulerService accessChangeSchedulerService = applicationContext.getBean(AccessChangeSchedulerService.class);
    AppContext appContext = applicationContext.getBean(AppContext.class);
    try {
        accessChangeSchedulerService.fetchAccessLevelChanges("EP", appContext.getSplunkToken());
    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }
}

Ваше здоровье.

Другие вопросы по теме