Reputation: 683
I created a standalone SpringBoot application, and created a new object in my main component,
but got a NullPointerException
at the new class.
How to use Autowired
correctly?
package com.aro.try.main;
import com.aro.try.model.AccountInfo;
import com.aro.try.service.AccountInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class MainProc implements CommandLineRunner {
@Autowired
private AccountInfoService accountInfoService;
@Override
public void run(String... args) throws Exception {
System.out.println("Hello MainProc~~~~~~");
// System.out.printf("account:" + accountInfoService.getAllAccountInfo());
new ABC().action();
}
}
class ABC {
@Autowired
private AccountInfoService accountInfoService;
public ABC() {
System.out.println("Init something~");
}
public void action(){
System.out.println("do action~");
System.out.println(accountInfoService.getAllAccountInfo());
}
}
Upvotes: 1
Views: 2609
Reputation: 513
@Autowired
only works on Spring managed classes, and in your case ABC
isn't one. To make ABC
managed by Spring, annotate it with @Component
. And then instead of instantiating ABC
explicitly in MainProc
, inject it using @Autowired
. AccountInfoService
can be removed from MainProc
if it isn't used there directly.
@Component
public class MainProc implements CommandLineRunner {
@Autowired
private ABC abc;
@Override
public void run(String... args) throws Exception {
System.out.println("Hello MainProc~~~~~~");
abc.action();
}
}
@Component
class ABC {
@Autowired
private AccountInfoService accountInfoService;
public ABC() {
System.out.println("Init something~");
}
public void action() {
System.out.println("do action~");
System.out.println(accountInfoService.getAllAccountInfo());
}
}
Bonus: Constructor Injection
It is generally recommended to use constructor injection instead of field injection. Its advantages are discussed here.
We usually advise people to use constructor injection for all mandatory collaborators and setter injection for all other properties. Again, constructor injection ensures all mandatory properties have been satisfied, and it is simply not possible to instantiate an object in an invalid state (not having passed its collaborators).
To use constructor injection, annotate the constructor with @Autowired
and include the dependency as a parameter. Then, remove @Autowired
from the field.
@Component
public class MainProc implements CommandLineRunner {
private ABC abc;
@Autowired
public MainProc(ABC abc) {
this.abc = abc;
}
@Override
public void run(String... args) throws Exception {
System.out.println("Hello MainProc~~~~~~");
abc.action();
}
}
@Component
public class ABC {
private AccountInfoService accountInfoService;
@Autowired
public ABC(AccountInfoService accountInfoService) {
this.accountInfoService = accountInfoService
System.out.println("Init something~");
}
public void action() {
System.out.println("do action~");
System.out.println(accountInfoService.getAllAccountInfo());
}
}
Upvotes: 3