有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Spring Boot中的java继承:@Autowired字段为null(需要在非Spring托管类的多个实例中自动连接)

我已经在运行基于注释的配置的Spring引导,但我对Spring还很陌生。我真的在别处找不到解决我问题的办法。 我有以下继承结构的任务对象:

  • 父任务
    • 系统任务
    • 用户任务
      • 特定用户任务

现在我想将一些存储库自动连接到SystemTask。我还想将存储库和一些服务自动连接到UserTask(及其所有子项)

我该怎么做?使用下面的代码,我得到一个空指针异常

家长:

public abstract class ParentTask implements Runnable {

    // some fields

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

    @Override
    public abstract void run();

}

第一个孩子:

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
    }
}

第二个孩子:

public abstract class UserTask extends ParentTask {

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

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

    @Override
    public abstract void run();

}

UserTask的子级(应具有UserTask的自动连接资源)

public class SpecificUserTask extends UserTask{

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

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

My Repository是一个标准的mongo Repository imlpement,不应该有任何错误。我的“someService”看起来像这样:

@Service
public class SomeService{

    // some fields

    @Autowired
    private someOtherRepository someOtherRepository;

    // some methods

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

我的问题是:

  1. 如何解决NullPointerException
  2. 如何在UserTask中自动关联字段,使其在SpecificUserClass中可用

提前谢谢大家

编辑:这是我在需要时创建新任务的方式:

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

共 (2) 个答案

  1. # 1 楼答案

    您需要在SpecificUserTask类上添加注释,如@Component。然后当您@Autowired您的SpecificUserTaskspring将为它注入所有内容,以及它的超类

    如果您没有使用Spring的特定注释对SpecificUserTask对象进行注释,那么Spring对它一无所知

    通过将一个bean的实例放置到另一个bean实例的字段中,可以实现自动连接。这两个类都应该是bean,并且应该“活”在应用程序上下文中

    在应用程序上下文中“生存”意味着上下文实例化对象,而不是您,您永远不应该使new MyClass()。容器找到每个注入点并在那里设置一个实例

    因此,当您使用诸如@Service@Component之类的注释对bean进行注释时,spring会找到它们并实例化

  2. # 2 楼答案

    我解决了我的问题,在非spring托管类中实际上需要一个自动连接的服务/存储库。 我使用了手动依赖注入,如下所述:
    How do I manually autowire a bean with Spring?

    这样,我可以拥有一个类的多个实例,也可以使用spring管理的服务。这是我现在的代码:

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