[英]Constructor Dependency Injection in Spring with abstract classes
I want to use Constructor Dependency Injection in my application.我想在我的应用程序中使用构造函数依赖注入。
I have created this controller:我已经创建了这个 controller:
public abstract class BonanzaCloudController {
protected final UserService userService;
protected BonanzaCloudController(UserService userService) {
this.userService = userService;
}
...
}
and this和这个
@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;
}
...
}
but I have this compilation error:但我有这个编译错误:
There is no default constructor available in BonanzaCloudController
AppErrorController
is a subclass of BonanzaCloudController
, so the constructor of AppErrorController
has to call the constructor of BonanzaCloudController
(by the rules defined by java). AppErrorController
是 BonanzaCloudController 的子类,因此BonanzaCloudController
的构造函数必须调用AppErrorController
的构造BonanzaCloudController
(由 java 定义的规则)。
Therefore the constructor of AppErrorController
has to be因此AppErrorController
的构造函数必须是
public AppErrorController(UserService userService, ErrorAttributes errorAttributes, EmailService emailService) {
super(userService);
this.errorAttributes = errorAttributes;
this.emailService = emailService;
}
Although the userService
doesn't have to be the first parameter, only the super()
call has to be first.虽然userService
不必是第一个参数,但只有super()
调用必须是第一个参数。
This is not a Spring DI issue but an issue with your class hierarchy.这不是 Spring DI 问题,而是 class 层次结构的问题。 To construct a AppErrorController
, the JVM will need to construct a basic instance of its superclass but you have not provided a way for it to do that.要构造AppErrorController
, JVM 将需要构造其超类的基本实例,但您尚未为其提供执行此操作的方法。 You will need to create a default constructor or explicitly call super(...)
and pass through an instance of UserService
too.您将需要创建一个默认构造函数或显式调用super(...)
并传递UserService
的实例。
This has nothing to do with Spring.这与 Spring 无关。 It's Java.它是 Java。
You have base class BonanzaCloudController
.你有基础 class BonanzaCloudController
。 You declare constructor there with 1 argument, means no-arg constructor won't be there anymore:你用 1 个参数声明构造函数,这意味着没有参数的构造函数将不再存在:
protected BonanzaCloudController(UserService userService) { }
Now you have a child class:现在你有了一个孩子 class:
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;
}
}
There is my small comment in the code above.上面的代码中有我的小注释。 When an instance of a child class is created - base class constructor is called first to instantiate the "base" part of the object.当创建子 class 的实例时 - 首先调用基本 class 构造函数来实例化 object 的“基本”部分。 In our case, it is super();
在我们的例子中,它是super();
and here it refers to no-arg constructor
in the base class (because it is just super()
, no args) and you simply don't have it in your base class.在这里它指的是基础 class 中的no-arg constructor
函数(因为它只是super()
,没有参数),而您的基础 class 中根本没有它。
So to fix this, you basically have 2 options.所以要解决这个问题,你基本上有两个选择。 First, you can call your constructor with param which you have in your base class:首先,您可以使用基础 class 中的参数调用构造函数:
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;
}
Or you can add no-arg constructor to your base class and then you don't need to call super at all.或者您可以将无参数构造函数添加到您的基础 class ,然后您根本不需要调用 super 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.