简体   繁体   English

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

[英]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.

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