Pole opatrzone adnotacjami @Autowired
jest null
spowodowane tym, że Spring nie wie o kopii MileageFeeCalculator
, którą utworzyłeś new
i nie wiedział, jak ją automatycznie zapisać.
Kontener Spring Inversion of Control (IoC) ma trzy główne elementy logiczne: rejestr (zwany ApplicationContext
) komponentami (komponentami bean), które są dostępne do użycia przez aplikację, system konfiguracyjny, który wstrzykuje do nich zależności obiektów poprzez dopasowanie zależności z komponentami bean w kontekście oraz solver zależności, który może spojrzeć na konfigurację wielu różnych komponentów bean i określić, jak utworzyć ich instancję i skonfigurować je w niezbędnej kolejności.
Kontener IoC nie jest magią i nie ma możliwości poznania obiektów Java, chyba że w jakiś sposób o nich poinformujesz. Podczas wywoływania new
JVM tworzy kopię nowego obiektu i przekazuje go prosto do Ciebie - nigdy nie przechodzi przez proces konfiguracji. Istnieją trzy sposoby skonfigurowania fasoli.
Wysłałem cały ten kod, używając Spring Boot do uruchomienia, w tym projekcie GitHub ; możesz spojrzeć na działający projekt dla każdego podejścia, aby zobaczyć wszystko, czego potrzebujesz, aby to zadziałało. Oznacz za pomocą NullPointerException
:nonworking
Wstrzyknij fasolę
Najkorzystniejszą opcją jest zezwolenie Springowi na automatyczne sterowanie wszystkimi twoimi ziarnami; wymaga to najmniejszej ilości kodu i jest najbardziej łatwe w utrzymaniu. Aby autouzupełnianie działało tak, jak chciałeś, wykonaj również autouzupełnianie w MileageFeeCalculator
następujący sposób:
@Controller
public class MileageFeeController {
@Autowired
private MileageFeeCalculator calc;
@RequestMapping("/mileage/{miles}")
@ResponseBody
public float mileageFee(@PathVariable int miles) {
return calc.mileageCharge(miles);
}
}
Jeśli musisz utworzyć nową instancję obiektu usługi dla różnych żądań, możesz nadal używać wstrzykiwania za pomocą zakresów komponentu Spring bean .
Tag, który działa poprzez wstrzyknięcie @MileageFeeCalculator
obiektu usługi:working-inject-bean
Użyj @Configurable
Jeśli naprawdę potrzebujesz obiektów utworzonych w new
celu automatycznego tworzenia, możesz użyć @Configurable
adnotacji Spring wraz z tkaniem czasu kompilacji AspectJ do wstrzyknięcia obiektów. To podejście wstawia kod do konstruktora obiektu, który ostrzega Springa, że jest tworzony, aby Spring mógł skonfigurować nowe wystąpienie. Wymaga to nieco konfiguracji w kompilacji (np. Kompilacji ajc
) i włączenia procedur konfiguracyjnych środowiska wykonawczego Springa ( @EnableSpringConfigured
ze składnią JavaConfig). Podejście to jest stosowane przez system Roo Active Record, aby umożliwić new
instancjom twoich jednostek uzyskanie niezbędnych informacji o trwałości.
@Service
@Configurable
public class MileageFeeCalculator {
@Autowired
private MileageRateService rateService;
public float mileageCharge(final int miles) {
return (miles * rateService.ratePerMile());
}
}
Tag, który działa przy użyciu @Configurable
obiektu usługi:working-configurable
Ręczne wyszukiwanie fasoli: niezalecane
To podejście nadaje się tylko do łączenia ze starszym kodem w szczególnych sytuacjach. Prawie zawsze preferowane jest utworzenie klasy adaptera singleton, którą Spring może automatycznie uruchomić, a starszy kod może wywoływać, ale możliwe jest bezpośrednie zapytanie kontekstu aplikacji Spring o komponent bean.
Aby to zrobić, potrzebujesz klasy, do której Spring może podać odwołanie do ApplicationContext
obiektu:
@Component
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getContext() {
return context;
}
}
Wówczas Twój starszy kod może wywoływać getContext()
i pobierać potrzebne ziarna:
@Controller
public class MileageFeeController {
@RequestMapping("/mileage/{miles}")
@ResponseBody
public float mileageFee(@PathVariable int miles) {
MileageFeeCalculator calc = ApplicationContextHolder.getContext().getBean(MileageFeeCalculator.class);
return calc.mileageCharge(miles);
}
}
Tag, który działa poprzez ręczne wyszukiwanie obiektu usługi w kontekście Spring: working-manual-lookup
F
wywołanie komponentu bean wewnątrz konstruktora innej fasoliS
. W takim przypadku przekaż wymaganą fasolęF
jako parametr do innegoS
konstruktora fasoli i dodaj adnotację do konstruktora zaS
pomocą@Autowire
. Pamiętaj, aby opisywanie klasy pierwszej fasoliF
z@Component
.