J'ai créé une simple classe Java dans l'application Spring Boot. appeler une méthode ns.mesage (); à partir de deux méthodes différentes, mais une est exécutée et une autre lance une exception de pointeur nul.
package TestPackage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/*
import TestPackage.MorningService;
import TestPackage.NightService;*/
@RestController
public class GenerateMessage {
@Autowired
public MorningService ms;
@Autowired
public NightService ns;
@RequestMapping(path = "/test")
public String starter(){
GenerateMessage gm=new GenerateMessage();
ns.mesage(); // this call working fine
gm.mes();
return "Mail scheduled.";
}
public void mes(){
try{
System.out.println("starts2..............");
ns.mesage(); // throwing an exception
}catch(Exception e){
e.printStackTrace();
}
}
}
3 Réponses :
Une fois que vous utilisez le mot-clé new , vous cassez toutes les injections utilisées avec @Autowired (cela signifie que le MorningService et NightService ne sera pas initialisé), c'est pourquoi vous obtenez un NPE.
Si vous voulez vraiment tester votre méthode mes () depuis votre contrôleur, implémentez dans votre classe @SpringBootApplication l'interface CommandLineRunner .
Ensuite, vous pouvez injecter un bean GenerateMessage avec @ Autowired et testez votre méthode.
Voici un exemple:
@SpringBootApplication
public class MainApplication implements CommandLineRunner {
@Autowired
private GenerateMessage generateMessage;
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
generateMessage.mes();
}
}
Lorsque vous créez une instance avec le mot-clé new , elle ne passe pas par le cycle de vie du spring bean. Dans un post-processeur de résultat, quelle réponse pour le traitement de l'annotation @Autowired ne fonctionne pas et NightService n'est pas injecté dans une nouvelle instance de GenerateMessage. Vous créez juste une instance de la classe avec des champs nuls.
Si vous voulez créer un vrai bean manuellement, vous devriez le faire comme ceci:
@RestController
public class GenerateMessage {
@Autowired
public MorningService ms;
@Autowired
public NightService ns;
@Autowired
private ApplicationContext applicationContext;
@RequestMapping(path = "/test")
public String starter(){
GenerateMessage gm=applicationContext.getBean(GenerateMessage.class);
ns.mesage(); // this call working fine
gm.mes();
return "Mail scheduled.";
}
public void mes(){
try{
System.out.println("starts2..............");
ns.mesage(); // throwing an exception
}catch(Exception e){
e.printStackTrace();
}
}
}
Mais je ne recommande pas vous travaillez directement avec le contexte d'application, car il s'agit d'un objet lourd et peut entraîner une diminution des performances.
Vous ne devez pas mélanger l'utilisation de new avec Autowired.
Une fois que vous utilisez le nouveau mot-clé, vous interrompez toutes les injections utilisées avec @Autowired (cela signifie que MorningService et NightService ne seront pas initialisés), c'est pourquoi vous obtenez un NPE.
Soulution No.1
utilisez AUTOWIRE
@RequestMapping(path = "/test")
public String starter(){
// GenerateMessage gm=new GenerateMessage();
ns.mesage(); // this call working fine
this.mes();
return "Mail scheduled.";
}
Solution n ° 2
utilisez ce mot-clé
@Autowired
public MorningService ms;
@Autowired
public NightService ns;
@Autowired
GenerateMessage gm;
@RequestMapping(path = "/test")
public String starter(){
// GenerateMessage gm=new GenerateMessage();
ns.mesage(); // this call working fine
gm.mes();
return "Mail scheduled.";
}
Veuillez publier la trace complète de la pile et veuillez suivre la dénomination appropriée, gm, ns ne sont pas des noms valides, utilisez plutôt nightService et morningService.
où sont définies vos dépendances?