繁体   English   中英

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

[英]Constructor Dependency Injection in Spring with abstract classes

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

我已经创建了这个 controller:

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 的子类,因此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 问题,而是 class 层次结构的问题。 要构造AppErrorController , JVM 将需要构造其超类的基本实例,但您尚未为其提供执行此操作的方法。 您将需要创建一个默认构造函数或显式调用super(...)并传递UserService的实例。

这与 Spring 无关。 它是 Java。

你有基础 class BonanzaCloudController 你用 1 个参数声明构造函数,这意味着没有参数的构造函数将不再存在:

protected BonanzaCloudController(UserService userService) { }

现在你有了一个孩子 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;
    }

}

上面的代码中有我的小注释。 当创建子 class 的实例时 - 首先调用基本 class 构造函数来实例化 object 的“基本”部分。 在我们的例子中,它是super(); 在这里它指的是基础 class 中的no-arg constructor函数(因为它只是super() ,没有参数),而您的基础 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;
}

或者您可以将无参数构造函数添加到您的基础 class ,然后您根本不需要调用 super 。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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