780 Stimmen

Warum ist mein Spring @Autowired-Feld null?

Hinweis: Dies soll eine kanonische Antwort für ein häufiges Problem sein.

Ich habe eine Spring @Service-Klasse (MileageFeeCalculator), die ein @Autowired-Feld (rateService) hat, aber das Feld ist null, wenn ich versuche, es zu verwenden. Die Protokolle zeigen, dass sowohl das MileageFeeCalculator-Bean als auch das MileageRateService-Bean erstellt werden, aber ich erhalte eine NullPointerException, wenn ich versuche, die Methode mileageCharge auf meinem Service-Bean aufzurufen. Warum verkabelt Spring das Feld nicht automatisch?

Controller-Klasse:

@Controller
public class MileageFeeController {
    @RequestMapping("/mileage/{miles}")
    @ResponseBody
    public float mileageFee(@PathVariable int miles) {
        MileageFeeCalculator calc = new MileageFeeCalculator();
        return calc.mileageCharge(miles);
    }
}

Service-Klasse:

@Service
public class MileageFeeCalculator {

    @Autowired
    private MileageRateService rateService; // <--- sollte autowired sein, ist null

    public float mileageCharge(final int miles) {
        return (miles * rateService.ratePerMile()); // <--- wirft NPE
    }
}

Service-Bean, das in MileageFeeCalculator autowired werden sollte, aber nicht ist:

@Service
public class MileageRateService {
    public float ratePerMile() {
        return 0.565f;
    }
}

Wenn ich versuche, GET /mileage/3, erhalte ich diese Ausnahme:

java.lang.NullPointerException: null
    at com.chrylis.example.spring_autowired_npe.MileageFeeCalculator.mileageCharge(MileageFeeCalculator.java:13)
    at com.chrylis.example.spring_autowired_npe.MileageFeeController.mileageFee(MileageFeeController.java:14)
    ...

4voto

yglodt Punkte 12422

Beachten Sie auch, dass wenn Sie aus irgendeinem Grund eine Methode in einem @Service als final kennzeichnen, werden die autowired Beans, auf die Sie zugreifen, immer null sein.

2voto

Abhishek Punkte 1442

Sie können dieses Problem auch beheben, indem Sie die @Service-Annotation auf der Serviceklasse verwenden und die erforderliche Bean-KlasseA als Parameter an den Konstruktor der anderen Bean-KlasseB übergeben und den Konstruktor der KlasseB mit @Autowired annotieren. Beispiel-Schnipsel hier :

@Service
public class ClassB {

    private ClassA classA;

    @Autowired
    public ClassB(ClassA classA) {
        this.classA = classA;
    }

    public void useClassAObjectHere(){
        classA.callMethodOnObjectA();
    }
}

1voto

Rishabh Agarwal Punkte 1631

Dies gilt nur im Falle des Unit-Tests.

Meine Service-Klasse hatte eine Annotation von Service und es war @autowired eine andere Komponentenklasse. Als ich die Komponentenklasse getestet habe, kam sie null. Denn für die Service-Klasse habe ich das Objekt mit new erstellt.

Wenn Sie einen Unit-Test schreiben, stellen Sie sicher, dass Sie kein Objekt mit new object() erstellen. Verwenden Sie stattdessen injectMock.

Dies hat mein Problem behoben. Hier ist ein nützlicher Link

0voto

Arefe Punkte 8879

Nicht direkt mit der Frage zusammenhängend, aber wenn die Feldinjektion null ist, funktioniert die Konstruktor-basierte Injektion trotzdem einwandfrei.

    private OrderingClient orderingClient;
    private Sales2Client sales2Client;
    private Settings2Client settings2Client;

    @Autowired
    public BrinkWebTool(OrderingClient orderingClient, Sales2Client sales2Client, Settings2Client settings2Client) {
        this.orderingClient = orderingClient;
        this.sales2Client = sales2Client;
        this.settings2Client = settings2Client;
    }

0voto

Sean Punkte 777

Zusätzlich, injizieren Sie nicht in ein static Mitglied, es wird null sein.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X