簡體   English   中英

Spring Autowiring 提供 NPE。 不手動創建bean

[英]Spring Autowiring giving NPE. not manually creating beans

在運行應用程序時,我的 spring MVC 程序中的服務類仍然為空。 這兩個類都是 @Service 並且在控制器類中有 @Autowired 但仍然為空。 我已經瀏覽了幾天,我發現的只有兩個原因,這兩個(我相信)都不適用於我的情況。

Spring Boot 應用程序試圖創建一個不和諧的機器人,自動裝配在控制器或 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;

突襲管理服務:

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

封裝結構:

  • 電腦
    • 死亡
      • 死亡機器人應用程序
      • 控制器
        • 死亡機器人命令列表器
      • 服務
        • RaidAdminService(接口)
        • RaidAdminServiceImpl(類)....

當程序啟動並運行時,在不和諧服務器中發送“!open”,正確點擊 switch 語句並嘗試調用 createRaid 方法,但 RaidAdminService 未自動裝配,因此它在 null 上調用該方法。

我認為問題出在您的 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.

您手動實例化了對象,因此 Spring 不知道該 bean。 這就是為什么您的 @Autowired 字段為空的原因。

Spring boot 必須先加載主類,然后通過這些類繼續注入 bean。

擴展 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 而不是“靜態”時才有效。

看那個 :

@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(但僅在實例字段中)。
您的問題確實很常見:您希望在依賴於某些 bean 的 Spring Boot 應用程序類的 main() 中執行一些任務。
正確的方法是使用@PostConstruct注釋。 一旦在當前 bean 上執行依賴注入,就會(自動)執行一個帶有注釋的方法:這里是 Spring Boot 應用程序。
它會給:

@Autowired
private BotCommandListener botListener;

@PostConstruct
public void init(){    
    JDA jda = new JDABuilder(AccountType.BOT)
        .setToken(TOKEN)
        .addEventListener(botListener)
        .build(); 
       // ...    
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM