Home > other >  How to use SpringBoot @Autowired in new class constructor
How to use SpringBoot @Autowired in new class constructor

Time:02-01

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());
    }
}

CodePudding user response:

@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());
    }
}
  •  Tags:  
  • Related