• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Dependency injection not recommended - null pointer

Object Storage Arubacloud
0 głosów
261 wizyt
pytanie zadane 14 września 2018 w Java przez Pablo93 Użytkownik (800 p.)
edycja 14 września 2018 przez Pablo93

Witam 

Mam straszny problem z wstrzyknięciem zależnosci , chodzi o to że kończy się ona null pointer exception

Posiadam interface 

package com.example.demo;
public interface inter {
    public void sout();
}

Oraz jego implementację (tutaj akurar @Component ) ale nawet gdy mam @Service jest to samo

package com.example.demo;

import org.springframework.stereotype.Component;

@Component
public class interImpl implements inter {

    @Override
    public void sout() {
        System.out.println("Udało Się");
    }
}

Oraz klasę w której chcę dodać dependency 

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    @Autowired
    static interImpl inter;

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


        inter.sout();
    }
}

I odpalenie takiego kodu kończy się :

Exception in thread "main" java.lang.NullPointerException 

Po odpaleniu tego kodu w debagerze okazuje się ze obiekt inter jest pusty. Szukam od dłuższego czasu odp dlaczego tak się dzieje ale nie mogę znaleźć

https://zapodaj.net/499ebb902b4f8.png.html

Link do projektu :

http://hostuje.net/file.php?id=9520baf3355db04f66da7976ac44d841

3 odpowiedzi

–1 głos
odpowiedź 14 września 2018 przez adas94 Nałogowiec (29,200 p.)
wybrane 23 września 2018 przez Pablo93
 
Najlepsza

Wyrzuca ci błąd ponieważ tworzysz obiekt poprzez new. Jeżeli chcesz wywoływać metody wstrzykniętego obiektu w mainie to dodaj sobie interfejs CommandLineRunner i wywołuj wszystko w metodzie run();

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

    @Autowired
    interImpl inter;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
    
    @Override
    public void run(String... args) throws Exception {
        inter.sout();
    }
}

Druga sprawa to do teraz nie wiem po co stworzyłeś interfejs Inter, skoro z niego w ogóle nie korzystasz, a wstrzykujesz bezpośrednio konkretną klasę do konkretnego typu. Zmień interImpl inter na inter inter (No i klasy i interfejsy powinieneś rozpoczynać dużą literą)

komentarz 23 września 2018 przez Pablo93 Użytkownik (800 p.)
Douczyłem się z interface'ów i po stworzeniu interface oraz jego implementacji działa jak szalone
0 głosów
odpowiedź 14 września 2018 przez mbabane Szeryf (79,280 p.)
Bo jest static.
komentarz 14 września 2018 przez Pablo93 Użytkownik (800 p.)

Zmieniłem kod na 

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    @Autowired
    interImpl inter;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
        DemoApplication demoApplication = new DemoApplication();
        demoApplication.ff();
    }

    public void ff (){
        inter.sout();
    }
}

I nadal null 
 

komentarz 14 września 2018 przez mbabane Szeryf (79,280 p.)
edycja 14 września 2018 przez mbabane

Tu chodzi zdaje się o to, że wstrzykiwanie można robić tylko do beanow zarządzanych przez spring. Tworząc obiekt  za pomocą new DemoApplication nie jest on zarządzany przez kontener spring, dlatego spring go nie wstrzykuje (znaczy wstrzykuje, ale nie do tego obiektu). Aby dostać się do tego obiektu ze wstrzykniętą zależnością trzeba by zrobić tak:

ConfigurableApplicationContext ctx =  SpringApplication.run(DemoApplication.class, args);
DemoApplication demoApplication = ctx.getBean(DemoApplication.class);
demoApplication.ff();

 

komentarz 15 września 2018 przez Wiciorny Ekspert (270,150 p.)

Spring będzie zarządzał obiektem interImpl... bo jest to Component, problem polega na tym, że w "właśnie tak jak twój drugi kod pokazuje "  spring obecnie traktuje Context IoC jako 

SpringApplication.run(DemoApplication.class, args);

co wyklucza w zasadzie dowiązanie binów które, mimo iż stanowią komponent,   są bezużyteczne w Context- path. stąd trzeba jasno określić że chcemy je wprowadzić do kontekstu na zasadzie INSTANCJI, a nie wiązania du PUSTEJ REFERENCJI. 

Po prostu obiekt nie zostanie zainicjalizowany przez kontener springowy, bo nie wymaga tego kontext, natomiast- automatyczne dowiązanie zachodzi do puster referencji 

1
komentarz 15 września 2018 przez mbabane Szeryf (79,280 p.)

Spring będzie zarządzał obiektem interImpl... 

Chyba, źle to zrozumiałeś. Chodziło mi o to że spring nie zarządza takim obiektem:

DemoApplication da = new DemoApplication();

 

komentarz 15 września 2018 przez Wiciorny Ekspert (270,150 p.)
no jeśli będzie w Main, to oczywiście żę nie [ ale wiąże w kolegi przykładzie PUSTĄ REFERENCJE ]  ... no nie należy do CONTEXTU  wtedy ten obiekt, zresztą mój przykład automatycznego wiązania jest właśnie odpowiedzią bo wymusza tworzenie obiektu przez IOC Springowe
0 głosów
odpowiedź 15 września 2018 przez Wiciorny Ekspert (270,150 p.)

@SpringBootApplication
public class DemoApplication {

    static  interImpl inter;

    @Autowired
    public DemoApplication(interImpl inter) {
        this.inter = inter;
    }

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


        inter.sout();
    }
}

 

Log:

 2018-09-15 21:40:03.381  INFO 4652 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 7.548 seconds (JVM running for 8.853)
Udało Się
 

Dlaczego Automatyczne wiązanie przez pole jest niedobre w tym wypadku ?

Bo - obiekt który ma być wstrzyknięty... zostaje WSTRZYKNIĘTY, ale jest to referencja pusta? Dlaczego- bo inicjalizacja nie zachodzi? Dlaczego? Bo Element, nie należy do kontekstu- są drwa rozwiązania, albo ustawiasz kontekst BEANA, w funkkcji run ( tak jak np mbabane napisał ). żeby spring wiedział co jest kontekstem i że należy zainicjalizować obiekt 

ew. napisać wiązanie automatyczne przez konstruktor KTÓRE JEST ZDECYDOWANIE NAJLEPSZĄ PRAKTYKĄ :) i automatycznie to wskazuje, że " instancja twojego  interIMPL jest składową context patch ) 

 

Podobne pytania

0 głosów
3 odpowiedzi 260 wizyt
pytanie zadane 27 lutego 2018 w Java przez kosttek Początkujący (450 p.)
0 głosów
2 odpowiedzi 293 wizyt
pytanie zadane 20 stycznia 2019 w PHP przez niezalogowany
0 głosów
1 odpowiedź 356 wizyt
pytanie zadane 20 stycznia 2019 w PHP przez niezalogowany

92,573 zapytań

141,423 odpowiedzi

319,648 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...