Java Spring中抽象类的构造函数依赖注入

Java Spring中抽象类的构造函数依赖注入,java,spring,spring-boot,spring-mvc,Java,Spring,Spring Boot,Spring Mvc,我想在我的应用程序中使用构造函数依赖项注入 我已创建此控制器: public abstract class BonanzaCloudController { protected final UserService userService; protected BonanzaCloudController(UserService userService) { this.userService = userService; } ... } 还有这个

我想在我的应用程序中使用构造函数依赖项注入

我已创建此控制器:

public abstract class BonanzaCloudController {


    protected final UserService userService;

    protected BonanzaCloudController(UserService userService) {
        this.userService = userService;
    }

...
}
还有这个

@Controller
public class AppErrorController extends BonanzaCloudController implements ErrorController {

    private final ErrorAttributes errorAttributes;    

    private final EmailService emailService;

    public AppErrorController(ErrorAttributes errorAttributes, EmailService emailService) {
        this.errorAttributes = errorAttributes;
        this.emailService = emailService;
    }
...
}
但我有一个编译错误:

There is no default constructor available in BonanzaCloudController

AppErrorController
BonanzaCloudController
的子类,因此
AppErrorController
的构造函数必须调用
BonanzaCloudController
的构造函数(根据java定义的规则)

因此,
AppErrorController
的构造函数必须是

public AppErrorController(UserService userService, ErrorAttributes errorAttributes, EmailService emailService) {
    super(userService);
    this.errorAttributes = errorAttributes;
    this.emailService = emailService;
}

尽管
userService
不必是第一个参数,但只有
super()
调用必须是第一个参数。

这不是Spring DI的问题,而是类层次结构的问题。要构造一个
AppErrorController
,JVM将需要构造其超类的一个基本实例,但您还没有为它提供这样做的方法。您需要创建一个默认构造函数或显式调用
super(…)
并传递
UserService
的实例。

这与Spring无关。它是Java

您拥有基类
BonanzaCloudController
。使用1个参数在那里声明构造函数,意味着没有参数构造函数将不再存在:

protected BonanzaCloudController(UserService userService) { }
现在您有了一个子类:

public class AppErrorController extends BonanzaCloudController {

    public AppErrorController(ErrorAttributes errorAttributes, EmailService emailService) {
        // this is how your constructor looks, super is implicit there
        // means that you don't need to add it, it will be there anyway.
        super();
        this.errorAttributes = errorAttributes;
        this.emailService = emailService;
    }

}
上面的代码中有我的小注释。创建子类的实例时,首先调用基类构造函数来实例化对象的“基”部分。在我们的例子中,它是
super()无arg构造函数
(因为它只是
super()
,没有args),而基类中根本没有它

所以要解决这个问题,你基本上有两个选择。首先,可以使用基类中的param调用构造函数:

public AppErrorController(ErrorAttributes errorAttributes, EmailService emailService) {
    // the first call should be an explicit call of super(...)
    // as a param you need instance of UserService
    super(userService);
    this.errorAttributes = errorAttributes;
    this.emailService = emailService;
}

或者,您可以不向基类添加参数构造函数,这样就根本不需要调用super。

您的抽象类应该在层次结构下有一个实现。如果您的抽象类是这里唯一的类,那么它没有任何用途,因为JVM无法创建它的实例。