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