Я создаю приложение 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)




вы можете создать класс, реализующий CommandLineRunner, и он будет вызываться после запуска приложения.
@Component
public class CommandLineAppStartupRunner implements CommandLineRunner {
@Autowired
private MyService myService;
@Override
public void run(String...args) throws Exception {
myService.save();
}
}
вы можете получить более подробную информацию об этом здесь
Работал! Спасибо
Есть ли способ вызвать метод с терминала? Я имею в виду метод save ().
@ ken4ward, в основном нет прямого способа вызвать определенную функцию внутри всего приложения без вызова всего приложения ... вы можете обойти это с помощью многих функций Spring, таких как профили, условные классы и переменные env, что такое ваш вариант использования именно?
Используя ключевое слово 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));
}
}
спаси мою ночь :)
Проблема с вашим кодом в том, что вы не искали 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();
}
}
Ваше здоровье.
экземпляр, который вы создаете в основном, не совпадает с экземпляром Springboot; вы можете удалить эти строки в main и вместо этого добавить аннотацию
@PostContructповерх myMethod ()