简体   繁体   中英

Inheritance in Spring Boot: @Autowired fields are null (need autowiring in non spring managed class - multiple instances)

i've got Spring Boot with annotation based configuration running, but I#m pretty new to spring. I really could not find a solution to my problem elsewhere. I've got Task objects with the following inheritance structure:

  • ParentTask
    • SystemTask
    • UserTask
      • SpecificUserTask

Now I want to autowire some Repository to the SystemTask. Also I want to autowire the Repository and some Service to the UserTask (and all of its children).

How do I do this? With the following code I get a Null Pointer Exception.

the parent:

public abstract class ParentTask implements Runnable {

    // some fields

    protected ParentTask(/*fields*/) {
        //this.fields = fields;
    }

    @Override
    public abstract void run();

}

the first child:

public class SystemTask extends ParentTask {

    @Autowired
    protected SomeService someService;

    protected SystemTask(/*fields*/) {
        super(fields);
        //set some other fields
    }

    @Override
    public void run() {
        someService.doSomething(); // <-- nullPointerException
    }
}

the second child:

public abstract class UserTask extends ParentTask {

    @Autowired
    protected SomeService someService;
    @Autowired
    protected SomeRepository someRepository;

    protected UserTask(/*fields*/) {
        super(fields);
    }

    @Override
    public abstract void run();

}

child of UserTask (shall have the autowired ressources of UserTask)

public class SpecificUserTask extends UserTask{

    private SpecificUserTask (/*fields*/) {
        super(fields);
        //set some other fields
    }

    @Override
    public void run() {
        // do something
    }
}

My Repository is a standard mongo repository imlpementation and should not have any errors. My "someService" looks something like this:

@Service
public class SomeService{

    // some fields

    @Autowired
    private someOtherRepository someOtherRepository;

    // some methods

    public void doSomething() {
        //...
    }
}

So again my questions:

  1. How do I resolve the NullPointerException?
  2. How do I autowire fields in UserTask so they are available in SpecificUserClass?

Thank you all in advance.

EDIT: this is how I create a new Task whenever needed:

@Service
public class TaskAdministration {

    private final TaskAdministrationRepository taskAdministrationRepository;

    public void commissionSystemTask(fields) {

        SystemTask task = new SystemTask(fields);
        taskScheduler.schedule(task, taskTrigger);

        // persist task to restore if necessary
        taskAdministrationRepository.save(task);
    }
}

You need to put annotation on your SpecificUserTask class like @Component . And then when you @Autowired your SpecificUserTask spring will inject everything for it and it's super classes.

Spring doesn't know anything about your SpecificUserTask object if you're not annotating it with spring's specific annotation.

Autowiring happens by placing an instance of one bean into the field in an instance of another bean. Both classes should be beans and should "live" in application context.

"living" in the application context means that the context instantiates the objects, not you, you should never make new MyClass() . The container finds each injection point and sets an instance there.

So when you're annotating bean with annotation like @Service or @Component spring finds them and instantiates.

I resolved my Problem, which was actually needing an autowired service/repository in a non-spring managed class. I used manual dependency injection like described here:
How do I manually autowire a bean with Spring?

This way I can have multiple instances of a class and also use services managed by spring. This is my code now:

@Service
public class TaskAdministration {

    @Autowired
    private ApplicationContext appContext;

    private final TaskAdministrationRepository taskAdministrationRepository;

    public void commissionSystemTask(fields) {

        SystemTask task = new SystemTask(trigger);
        AutowireCapableBeanFactory factory = appContext.getAutowireCapableBeanFactory();
        factory.autowireBean( task );
        factory.initializeBean( task, "SystemTask" );

        taskScheduler.schedule(task, task.trigger);

        // persist task to restore if necessary
        taskAdministrationRepository.save(task);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM