java - Why is my Spring @Autowired field null? -
note: intended canonical reply mutual problem.
i have spring @service class (mileagefeecalculator) has @autowired field (rateservice), field null when seek utilize it. logs show both mileagefeecalculator bean , mileagerateservice bean beingness created, nullpointerexception whenever seek phone call mileagecharge method on service bean. why isn't spring autowiring field?
controller class:
@controller public class mileagefeecontroller { @requestmapping("/mileage/{miles}") @responsebody public float mileagefee(@pathvariable int miles) { mileagefeecalculator calc = new mileagefeecalculator(); homecoming calc.mileagecharge(miles); } } service class:
@service public class mileagefeecalculator { @autowired private mileagerateservice rateservice; // <--- should autowired, null public float mileagecharge(final int miles) { homecoming (miles * rateservice.ratepermile()); // <--- throws npe } } service bean should autowired in mileagefeecalculator isn't:
@service public class mileagerateservice { public float ratepermile() { homecoming 0.565f; } } when seek get /mileage/3, exception:
java.lang.nullpointerexception: null @ com.chrylis.example.spring_autowired_npe.mileagefeecalculator.mileagecharge(mileagefeecalculator.java:13) @ com.chrylis.example.spring_autowired_npe.mileagefeecontroller.mileagefee(mileagefeecontroller.java:14) ...
the field annotated @autowired null because spring doesn't know re-create of mileagefeecalculator created new , didn't know autowire it.
the spring inversion of command (ioc) container has 3 main logical components: registry (called applicationcontext) of components (beans) available used application, configurer scheme injects objects' dependencies them matching dependencies beans in context, , dependency solver can @ configuration of many different beans , determine how instantiate , configure them in necessary order.
the ioc container isn't magic, , has no way of knowing java objects unless somehow inform of them. when phone call new, jvm instantiates re-create of new object , hands straight you--it never goes through configuration process. there 3 ways can beans configured.
i have posted of code, using spring boot launch, @ this github project; can @ total running project each approach see need create work. tag nullpointerexception: nonworking
the preferable alternative allow spring autowire of beans; requires to the lowest degree amount of code , maintainable. create autowiring work wanted, autowire mileagefeecalculator this:
@controller public class mileagefeecontroller { @autowired private mileagefeecalculator calc; @requestmapping("/mileage/{miles}") @responsebody public float mileagefee(@pathvariable int miles) { homecoming calc.mileagecharge(miles); } } if need create new instance of service object different requests, can still utilize injection using the spring bean scopes.
tag works injecting @mileagefeecalculator service object: working-inject-bean
if need objects created new autowired, can use spring @configurable annotation along aspectj compile-time weaving inject objects. approach inserts code object's constructor alerts spring it's beingness created spring can configure new instance. requires bit of configuration in build (such compiling ajc) , turning on spring's runtime configuration handlers (@enablespringconfigured javaconfig syntax). approach used roo active record scheme allow new instances of entities necessary persistence info injected.
@service @configurable public class mileagefeecalculator { @autowired private mileagerateservice rateservice; public float mileagecharge(final int miles) { homecoming (miles * rateservice.ratepermile()); } } tag works using @configurable on service object: working-configurable
this approach suitable interfacing legacy code in special situations. preferable create singleton adapter class spring can autowire , legacy code can call, possible straight inquire spring application context bean.
to this, need class spring can give reference applicationcontext object:
@component public class applicationcontextholder implements applicationcontextaware { private static applicationcontext context; @override public void setapplicationcontext(applicationcontext applicationcontext) throws beansexception { context = applicationcontext; } public static applicationcontext getcontext() { homecoming context; } } then legacy code can phone call getcontext() , retrieve beans needs:
@controller public class mileagefeecontroller { @requestmapping("/mileage/{miles}") @responsebody public float mileagefee(@pathvariable int miles) { mileagefeecalculator calc = applicationcontextholder.getcontext().getbean(mileagefeecalculator.class); homecoming calc.mileagecharge(miles); } } tag works manually looking service object in spring context: working-manual-lookup
java spring null nullpointerexception autowired
No comments:
Post a Comment