web-dev-qa-db-fra.com

Spring io @Autowired: Le champ final vide n'a peut-être pas été initialisé

ce que je suppose est une question assez basique ici-

Il existe plusieurs saveurs de questions concernant cette erreur, mais aucune dans les 5 premiers résultats qui ont la nuance supplémentaire de Spring.

J'ai les débuts d'une webapp REST-ful écrite au printemps. J'essaie de le connecter à une base de données.

J'ai une entité nommée Workspace et j'essaie d'utiliser l'injection printanière d'un bean (terminologie correcte?) Pour enregistrer une instance de l'entité de l'espace de travail

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);
    }
}

Mon erreur est sur la variable de référentiel private final WorkspaceRepository repository. Le compilateur se plaint de ne pas avoir été initialisé et la tentative d'exécution de l'application donne le même résultat.

Comment puis-je obtenir une instance de cet objet de référentiel dans mon contrôleur afin d'effectuer des opérations de sauvegarde sur celui-ci?

21
Pinwheeler

Ayant @Autowired et final sur un champ sont contradictoires.

Ce dernier dit: cette variable a une et une seule valeur, et elle est initialisée au moment de la construction.

Le premier dit: Spring va construire l'objet, en laissant ce champ nul (sa valeur par défaut). Spring utilisera ensuite la réflexion pour initialiser ce champ avec un bean de type WorkspaceRepository.

Si vous voulez que les champs finaux soient câblés automatiquement, utilisez l'injection de constructeur, tout comme vous le feriez si vous faisiez l'injection vous-même:

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

Exactement, vous devez fournir un constructeur qui attribue le champ final

private final WorkspaceRepository repository;

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

Et Spring sera en mesure de comprendre comment initialiser l'objet et injecter le référentiel via le constructeur

9
Sleiman Jneidi