Пружина Автопроводка дача НПЭ.не создавать бобы вручную - PullRequest
1 голос
/ 02 июля 2019

Мои классы обслуживания в моей весенней программе MVC все еще нулевые при запуске приложения Оба класса являются @Service и имеют @Autowired в классе контроллера, но все еще имеют значение null. Я просмотрел несколько дней, и все, что я нашел, - это две причины, ни одна из которых (я считаю) не относится к моим обстоятельствам.

Загрузочное приложение Spring пытается создать диск-бот, автоматическое подключение не работает в контроллере или тесте Junit (NPE при выполнении, а переменная показывает ноль при отладке).

Класс вождения:

package com.deth;

//imports
@SpringBootApplication
public class DethBotApplication {


    private static Logger logger = Logger.getLogger(DethBotApplication.class);

    @Autowired
    private static BotCommandListener botListener;

    public static void main(String[] args)  {
        SpringApplication.run(DethBotApplication.class, args);


        try {
            JDA jda = new JDABuilder(AccountType.BOT)
                .setToken(TOKEN)
                //.addEventListener(command controller)
                .addEventListener(botListener)
                .build(); //starts listening in discord server.

Соответствующий код контроллера:

package com.deth.controller;
//imports
@Component  
public class BotCommandListener extends ListenerAdapter {


        private static Logger logger = Logger.getLogger(BotCommandListener.class);

        @Autowired
        @Qualifier("raidAdminService")
        private RaidAdminService raidAdminService; 

        @Autowired
        private RaidRosterServiceImpl raidRosterService;

        @Autowired
        private RaidAttendanceService raidAttendanceService;

        @Override
        public void onMessageReceived(MessageReceivedEvent event) {
            JDA jda = event.getJDA();

            String msg = event.getMessage().getContentDisplay();
            if(msg.startsWith("!")) {
                String command = "";
                if(!msg.contains(" ")) {
                    command = msg;
                } else {
                    command = msg.subSequence(0, msg.indexOf(" ")).toString();
                    logger.trace("possible command: " + command);
                }
                try {
                    switch (command) {
                    //raid leader commands
                    case "!open":
                        raidAdminService.createRaid(event); //NPE here
                        logger.trace("!open detected");
                        break;

raidAdminService:

package com.deth.service;
//imports
@Service("raidAdminService")
public class RaidAdminServiceImpl extends CommandInfoService implements RaidAdminService {

    String intRegex = "[0-9]+";

    @Override
    public void createRaid(MessageReceivedEvent event) {
        // TODO Auto-generated method stub

структура пакета:

  • ком
    • Deth
      • DethBotApplication
      • Контроллер
        • DethBotCommandListner
      • Услуги
        • RaidAdminService (интерфейс)
        • RaidAdminServiceImpl (класс) ....

когда программа запущена и работает, отправьте «! Open» на дискорд-сервер, правильно нажав на оператор switch и попытавшись вызвать метод createRaid, но RaidAdminService не был подключен автоматически, поэтому его вызов метода равен нулю.

Ответы [ 4 ]

1 голос
/ 02 июля 2019

Я думаю, что проблема в вашем классе DethBotApplication. Вы не можете там подключиться автоматически. Основной класс должен быть выполнен в первую очередь. после этого приложение будет искать аннотации @Componet, @Service, @Controller .... код ниже может решить вашу проблему.

package com.deth;

//imports
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class DethBotApplication extends SpringBootServletInitializer {

    private static Logger logger = Logger.getLogger(DethBotApplication.class);

    public static void main(String[] args)  {
        ConfigurableApplicationContext context = SpringApplication.run(DethBotApplication.class, args);
        BotCommandListener botListener = context.getBean(BotCommandListener.class);
        try {
            JDA jda = new JDABuilder(AccountType.BOT)
                .setToken(TOKEN)
                //.addEventListener(command controller)
                .addEventListener(botListener)
                .build(); //starts listening in discord server.
0 голосов
/ 02 июля 2019

Посмотрите на это:

@Autowired
private static BotCommandListener botListener;

public static void main(String[] args)  {
    SpringApplication.run(DethBotApplication.class, args);
    try {
        JDA jda = new JDABuilder(AccountType.BOT)
            .setToken(TOKEN)
            .addEventListener(botListener)
     //...
    }

Вы аннотируете @Autowired статическое поле, в то время как Spring не вводит bean-компонент в статические поля (но только в полях экземпляра).
Ваша проблема действительно очень распространена: вы хотите выполнить некоторые задачи в main () класса приложения Spring Boot, которые зависят от некоторых bean-компонентов.
Правильный подход - использование аннотации @PostConstruct. Метод, аннотированный этим, (автоматически) выполняется после внедрения зависимости в текущий боб: здесь Spring Boot Application.
Это дало бы:

@Autowired
private BotCommandListener botListener;

@PostConstruct
public void init(){    
    JDA jda = new JDABuilder(AccountType.BOT)
        .setToken(TOKEN)
        .addEventListener(botListener)
        .build(); 
       // ...    
}
0 голосов
/ 02 июля 2019

Расширение класса ApplicationRunner или CommandLineRunner

package com.deth;

//imports
@SpringBootApplication
@Component
public class DethBotApplication implements CommandLineRunner {


    private static Logger logger = Logger.getLogger(DethBotApplication.class);

    @Autowired
    private /*static*/ BotCommandListener botListener; // i remove "static" here

    public static void main(String[] args)  {
        SpringApplication.run(DethBotApplication.class, args);

    }

    @Override
    public void run(String args) {
        try {
            JDA jda = new JDABuilder(AccountType.BOT)
                .setToken(TOKEN)
                //.addEventListener(command controller)
                .addEventListener(botListener)
                .build(); //starts listening in discord server.
    ... 

Ключ здесь (как указывают другие ответы) @Autowired работает, только если он является @Component, а не "статическим".

0 голосов
/ 02 июля 2019

Вы создали экземпляр объекта вручную, поэтому Spring не знает об этом бине.Вот почему ваше поле @Autowired имеет нулевое значение.

Spring boot должен сначала загрузить основной класс, а затем перейти к внедренному компоненту через эти классы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...