[英]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
封裝結構:
當程序啟動並運行時,在不和諧服務器中發送“!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.