- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我的“路线”文件中有这个:
POST /accounts/ controllers.AccountsController.createOneAccount
在我的 AccoutsController.java 中:
package controllers;
import com.google.inject.Inject;
import play.Application;
import play.mvc.Controller;
import play.mvc.Result;
import services.AccountService;
import java.io.IOException;
public class AccountsController extends Controller {
@Inject
private Application application;
final String host = application.configuration().getString("db.default.host");
final int port = application.configuration().getInt("db.default.port");
final String dbName = application.configuration().getString("db.default.dbname");
@Inject
private AccountService accountService;
public Result createOneAccount() throws IOException {
return accountService.createOneAccount(request().body().asJson());
}
}
此代码编译正常,但在运行时出现如下错误:
ProvisionException: Unable to provision, see the following errors: 1) Error injecting constructor, java.lang.NullPointerException at controllers.AccountsController.(AccountsController.java:11)
while locating controllers.AccountsController for parameter 1 at router.Routes.(Routes.scala:28) while locating router.Routes while locating play.api.inject.RoutesProvider while locating play.api.routing.Router for parameter 0 at play.api.http.JavaCompatibleHttpRequestHandler.(HttpRequestHandler.scala:200) while locating play.api.http.JavaCompatibleHttpRequestHandler while locating play.api.http.HttpRequestHandler for parameter 4 at play.api.DefaultApplication.(Application.scala:221) at play.api.DefaultApplication.class(Application.scala:221) while locating play.api.DefaultApplication while locating play.api.Application 1 error
我可以通过在路由文件中添加@来解决这个问题:
POST /accounts/ @controllers.AccountsController.createOneAccount
但我不确定为什么我需要这样做,以及如何避免“@”。请提出一些建议。
最佳答案
首先,请参阅此答案以了解在您的 routes
文件中使用或不使用 @
的区别:
https://stackoverflow.com/a/34867199/4600
然后,如 Play 2.5.x migration docs 所述:
Routes are now generated using the dependency injection aware
InjectedRoutesGenerator
, rather than the previousStaticRoutesGenerator
which assumed controllers were singleton objects.
因此,从 Play 2.5.0 开始, Controller 默认使用依赖注入(inject),您不需要 @
让它们使用依赖注入(inject)。
现在让我们看看您的案例中发生了什么。首先,让我说构造函数注入(inject)是注入(inject)依赖项的首选方式。 Guice 甚至建议(作为最佳实践)将 final
字段与构造函数注入(inject)结合到 minimize mutability . Guice 文档还建议您尝试 inject only direct dependencies .在您的情况下,您正在使用 application
访问 configuration
。为什么不注入(inject) configuration
对象呢?这将使您的依赖关系更加清晰(例如,这将使测试更容易)。
因此,按照此建议,您的代码将被重写为:
package controllers;
import com.google.inject.Inject;
import play.Configuration;
import play.mvc.Controller;
import play.mvc.Result;
import services.AccountService;
import java.io.IOException;
public class AccountsController extends Controller {
private final Configuration configuration;
private final AccountService accountService;
private final String host;
private final int port;
private final String dbName;
@Inject
public AccountsController(Configuration configuration, AccountService accountService) {
this.configuration = configuration;
this.accountService = accountService;
// initialize config variables
this.host = configuration.getString("db.default.host");
this.port = configuration.getInt("db.default.port");
this.dbName = configuration.getString("db.default.dbname");
}
public Result createOneAccount() throws IOException {
return accountService.createOneAccount(request().body().asJson());
}
}
我们首先需要了解对象初始化。根据Java specs :
Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:
Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.
If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.
Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.
Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.
特别注意第 4 步,它解释了您的变量是在对象初始化期间初始化的。
为什么这很重要?因为 Guice 首先创建对象(然后会发生上述所有步骤),然后执行注入(inject)绑定(bind)(有关更多详细信息,请参见 Guice Bootstrap 和 Guice InjectionPoints)。因此,在对象初始化时,您的字段需要尚未注入(inject)但会导致 NullPointerException
的变量 (application
)。
关于java - Play Framework 2.5.1 路由和依赖注入(inject)(适用于 Java),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36634019/
我已阅读有关依赖注入(inject)的信息。然后来了 构造函数注入(inject), setter/getter 注入(inject) 二传手注入(inject) 接口(interface)注入(in
我正在研究依赖注入(inject)模式。我看过很多例子,其中一个典型的例子是使用 XxxService/XxxRepository 作为例子。但是在我看来,按照UML的概念,类XxxRepositor
我开始使用 Google Guice。 我有一个简单的问题: javax.inject 的 @Inject 注释和 com.google.inject 的 有什么区别@Inject 一个 ? 谢谢。
当使用构造函数注入(inject)工厂方法时,依赖的属性不会得到解析。但是,如果在解析依赖的组件之前解析了工厂方法,则一切都会按预期工作。此外,当仅使用属性注入(inject)或构造函数注入(inje
我有这样的事情: class Root { public Root(IDependency dep) {} } class Dependency:IDependency { p
听完Clean Code Talks ,我开始明白我们应该使用工厂来组合对象。因此,例如,如果 House有一个 Door和 Door有一个 DoorKnob , 在 HouseFactory我们创建
情况:我需要在一些 FooClass 中进行惰性依赖实例化,所以我通过 Injector类作为构造函数参数。 private final Injector m_injector; public Foo
在编写代码时,我们应该能够识别两大类对象: 注入(inject)剂 新品 http://www.loosecouplings.com/2011/01/how-to-write-testable-cod
这个问题是关于 Unity Container 的,但我想它适用于任何依赖容器。 我有两个具有循环依赖关系的类: class FirstClass { [Dependency] pub
如果我有 10 个依赖项我需要注入(inject)并且不想在构造函数中有 10 个参数,我应该使用哪种注入(inject)模式? public class SomeClass { privat
我在使用 Angular2 DI 时遇到了问题。我尝试将一个类注入(inject)另一个类,它引发了以下错误: 留言:"Cannot resolve all parameters for 'Produ
对依赖注入(inject)还很陌生,我想弄清楚这是否是一种反模式。 假设我有 3 个程序集: Foo.Shared - this has all the interfaces Foo.Users -
我正在尝试了解 Angular 14 的变化,尤其是 inject()我可以将模块注入(inject)功能的功能,我不需要为此创建特殊服务..但我想我弄错了。 我正在尝试创建一些静态函数来使用包 ng
希望这个问题不是太愚蠢,我试图掌握更高级的编程原理,因此试图习惯使用 Ninject 进行依赖注入(inject)。 因此,我的模型分为几个不同的 .dll 项目。一个项目定义了模型规范(接口(int
我最近一直在大量使用依赖注入(inject)、测试驱动开发和单元测试,并且开始喜欢上它。 我在类中使用构造函数依赖,这样我就可以为单元测试注入(inject)模拟依赖。 但是,当您实际需要生产环境中的
我有下面的代码来使用 Guice 进行依赖注入(inject)。第一个是使用构造函数注入(inject),而另一个是直接在字段上方添加 @Inject。这两种方式有什么区别吗? Guice官网似乎推荐
这个问题在这里已经有了答案: Angular2 Beta dependency injection (3 个答案) 关闭 7 年前。 我正在使用 angular2 测试版。并在使用 @Inject
有没有可能做这样的事情? (因为我尝试过,但没有成功): @Injectable() class A { constructor(private http: Http){ // <-- Injec
我很恼火必须通过 Constructor 传递管道对象,因为我想为业务实体或要传递的值保留构造函数参数。 所以我想通过 setter ,但只要这些 setter 没有被填充,我的包含依赖项的对象就不应
假设我有这个: SomePage.razor: @inject Something something @page "/somepage" My Page @code { // Using
我是一名优秀的程序员,十分优秀!