web-dev-qa-db-fra.com

@autowired en classes statiques

Ceci est un projet Spring MVC avec Hibernate .Je suis en train de créer une classe Logger qui est responsable de la saisie des journaux dans la base de données . D'autres classes appellent juste les méthodes appropriées avec certains attributs magic . Par nature, il devrait s'agir d'une classe avec des méthodes statiques, mais cela pose des problèmes avec l'auto-hiérarchisation des objets dao.

public class StatisticLogger {
    @Autowired
    static Dao dao;
    public static void AddLoginEvent(LogStatisticBean user){
        //TODO code it god damn it
    }
    public static void AddDocumentEvent(LogStatisticBean user, Document document, DocumentActionFlags actionPerformed){
        //TODO code it god damn it
    }
    public static void addErrorLog(Exception e, String page,  HashMap<String, Object> parameters){
        ExceptionLogBean elb=new ExceptionLogBean();
        elb.setStuntDescription(e);
        elb.setSourcePage(page);
        elb.setParameters(parameters);
        if(dao!=null){ //BUT DAO IS NULL
            dao.saveOrUpdateEntity(elb);
    }
}

Comment y arriver? Que dois-je faire pour ne pas rendre dao object null? Je sais que je pourrais le passer en tant que paramètre de méthode, mais ce n'est pas très bon . , car ils sont créés trop tôt pour un mécanisme de hiérarchisation automatique n’a pas encore été créé.

19
T.G

Vous ne pouvez pas @Autowired un champ statique. Mais il y a une habileté délicate à résoudre:

@Component
public class StatisticLogger {

  private static Dao dao;

  @Autowired
  private Dao dao0;

  @PostConstruct     
  private void initStaticDao () {
     dao = this.dao0;
  }

}

Dans un mot, @Autowired un champ d’instance et affectez la valeur au fichier statique lors de la construction de votre objet. En passant, l’objet StatisticLogger doit également être géré par Spring. 

47
Weibo Li

Le câblage automatique classique ne fonctionnera probablement pas, car une classe statique n'est pas un bean et ne peut donc pas être gérée par Spring. Vous pouvez contourner ce problème, par exemple en utilisant le factory-method aproach dans XML , ou en chargeant les beans depuis un contexte Spring dans un bloc d’initialisation statique, mais je vous suggérerais de modifier votre conception:

N'utilisez pas de méthodes statiques, utilisez les services que vous injectez là où vous en avez besoin. Si vous utilisez Spring, vous pourriez aussi bien l'utiliser correctement. L'injection de dépendance est une technique orientée objet, et elle n'a de sens que si vous adoptez réellement la POO.

16
Sean Patrick Floyd

Je sais que c’est une vieille question, mais je voulais simplement partager ce que j’avais fait. La solution de @Weibo Li est ok mais le problème qu’il soulève est une alerte critique de Sonar sur l’affectation de variable non statique à une variable statique. 

la façon dont je l'ai résolu sans alertes sonar est la suivante

  1. Je change le StatisticLogger en singlton class (plus statique) Comme ceci

    classe publique StatisticLogger { instance statique privée StatisticLogger = null; Dao Dao privé;

    public static StatisticLogger getInstance() {
        if (instance == null) {
            instance = new StatisticLogger();
        }
        return instance;
    }
    
    protected StatisticLogger() {
    }
    
    public void setDao(Dao dao) {
        this.dao = dao;
    }
    public void AddLoginEvent(LogStatisticBean user){
        //TODO code it god damn it
    }
    public void AddDocumentEvent(LogStatisticBean user, Document document, DocumentActionFlags actionPerformed){
        //TODO code it god damn it
    }
    public  void addErrorLog(Exception e, String page,  HashMap<String, Object> parameters){
        ExceptionLogBean elb=new ExceptionLogBean();
        elb.setStuntDescription(e);
        elb.setSourcePage(page);
        elb.setParameters(parameters);
        if(dao!=null){ 
            dao.saveOrUpdateEntity(elb);
    }
    

    }

  2. J'ai créé un service (ou composant) qui connecte automatiquement le service que je veux et le place dans la classe singlton Ceci est sans danger car au printemps, il initialisera tous les beans gérés avant de faire quoi que ce soit, ce qui signifie que la méthode PostConstruct ci-dessous est toujours appelé avant tout peut accéder au StatisticLogger quelque chose comme ça

    @Component Public class DaoSetterService {

    @Autowired
    private Dao dao0;
    
    @PostConstruct     
    private void setDaoValue () {
        StatisticLogger.getInstance().setDao(dao0);
    }
    

    }

  3. Au lieu d'utiliser StatisticLogger en tant que classe statique, je l'utilise simplement en tant que StatisticLogger.getInstance () et je peux accéder à toutes les méthodes qu'elle contient.

0
Hani