【问题标题】:Spring io @Autowired: The blank final field may not have been initializedSpring io @Autowired:空白的最终字段可能尚未初始化
【发布时间】:2016-04-07 09:49:36
【问题描述】:

我认为这是一个非常基本的问题-

关于此错误有多种问题,但前 5 个结果中没有一个具有 Spring 的细微差别。

我有一个在春季编写的 REST-ful webapp 的开始。我正在尝试将其连接到数据库。

我有一个名为 Workspace 的实体,我正在尝试使用 bean 的 spring 注入(正确的术语?)来保存工作区实体的实例

package com.parrit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.parrit.models.Workspace;
import com.parrit.models.WorkspaceRepository;

@RestController
@RequestMapping("/workspace")
public class WorkspaceController {

    @Autowired
    private final WorkspaceRepository repository;

    @RequestMapping(method = RequestMethod.POST)
    void save( @RequestBody String workspaceHTML) {
        Workspace ws = new Workspace();
        ws.setHTML(workspaceHTML);
        repository.save(ws);
    }
}

我的错误在于存储库变量private final WorkspaceRepository repository。编译器抱怨它可能没有被初始化并且尝试运行应用程序会产生相同的结果。

如何将此存储库对象的实例放入我的控制器中以便对其进行保存操作?

【问题讨论】:

    标签: java spring spring-mvc spring-data


    【解决方案1】:

    @Autowired 和 final 在一个字段上是矛盾的。

    后者说:这个变量只有一个值,在构造时初始化。

    前者说:Spring 将构造对象,将该字段保留为 null(其默认值)。然后 Spring 将使用反射使用 WorkspaceRepository 类型的 bean 初始化该字段。

    如果您希望自动装配最终字段,请使用构造函数注入,就像您自己进行注入一样:

    @Autowired
    public WorkspaceController(WorkspaceRepository repository) {
        this.repository = repository;
    }
    

    【讨论】:

    • 有人必须创建一种方法来自动生成这个构造函数,让我们只拥有带有自动装配注释的最终字段。我确信 99% 的自动装配字段基本上都是最终的,即。 E. 初始化一次,再次初始化是错误的……目前的情况,这个约定只是默示而不是强制执行。
    • @masterxilo 使用 Kotlin。它促进和简化了不变性。请注意,在最近的 Spring 版本中,甚至不再需要构造函数上的 Autowired 注释。在 Kotli 中,您只需使用 class WorkspaceController(private val repository: WorkspaceRepository) { ... }
    • @JBNizet 字段在初始化之前不为空。它根本不是。 Foo bar = null;Foo bar; 不同。 “在编译时初始化”规则是一个错误。这在 Eclipse 中并不总是这样。在这种情况下,预编译检查对方法和类有意义,但对属性没有意义。
    【解决方案2】:

    没错,你必须提供一个构造函数来分配最终字段

    private final WorkspaceRepository repository;
    
    @Autowired
    public WorkspaceController(WorkspaceRepository repository){
      this.repository = repository;
    }
    

    Spring 将能够弄清楚如何初始化对象并通过构造函数注入存储库

    【讨论】:

      猜你喜欢
      • 2017-06-05
      • 1970-01-01
      • 2017-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多