@autowired en clases estáticas

Este es un proyecto Spring MVC con Hibernate. Estoy tratando de crear una clase Logger que sea responsable de ingresar los registros en la base de datos. Otras clases solo llaman a los métodos apropiados con algunos atributos y esta clase debería hacer toda la magia. Por naturaleza, debería ser una clase con métodos estáticos, pero eso causa problemas con el autoenvío del objeto 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 parameters){ ExceptionLogBean elb=new ExceptionLogBean(); elb.setStuntDescription(e); elb.setSourcePage(page); elb.setParameters(parameters); if(dao!=null){ //BUT DAO IS NULL dao.saveOrUpdateEntity(elb); } } 

¿Cómo hacerlo bien? ¿Qué debería hacer para no hacer que el objeto dao sea nulo? Sé que podría pasarlo como un parámetro de método, pero eso no es muy bueno. Supongo que el autoenlace no puede funcionar en objetos estáticos, porque se crearon para que el mecanismo de autoenvío no se haya creado todavía.

No puedes @Autowired un campo estático. Pero hay una habilidad difícil de tratar con esto:

 @Component public class StatisticLogger { private static Dao dao; @Autowired private Dao dao0; @PostConstruct private void initStaticDao () { dao = this.dao0; } } 

En una palabra, @Autowired un campo de instancia, y asigne el valor al archivo estático archivado cuando se construye su objeto. Por cierto, el objeto StatisticLogger debe ser administrado por Spring.

El autovínculo clásico probablemente no funcionará, porque una clase estática no es un frijol y, por lo tanto, Spring no puede gestionarlo. Hay formas de evitar esto, por ejemplo, utilizando el enfoque de factory-method en XML , o cargando los beans de un contexto de Spring en un bloque de inicializador estático, pero lo que sugeriría es cambiar su diseño:

No use métodos estáticos, use servicios que inyecte donde los necesite. Si usa Spring, es mejor que lo use correctamente. Dependency Injection es una técnica orientada a objetos, y solo tiene sentido si realmente adoptas OOP.

Sé que esta es una vieja pregunta, pero solo quería compartir lo que hice, la solución de @Weibo Li está bien, pero el problema que plantea Sonar Critical alert sobre la asignación de variable no estática a una variable estática

la forma en que lo resolví sin alertas de sonar es la siguiente

  1. Cambio el StatisticLogger a la clase de singlton (ya no estático) como este

    public class StatisticLogger {private static StatisticLogger instance = null; Dao privado;

     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 parameters){ ExceptionLogBean elb=new ExceptionLogBean(); elb.setStuntDescription(e); elb.setSourcePage(page); elb.setParameters(parameters); if(dao!=null){ dao.saveOrUpdateEntity(elb); } 

    }

  2. Creé un servicio (o Componente) que conecta automáticamente el servicio que quiero y lo configuro en la clase individual. Esto es seguro ya que en spring inicializará todos los beans administrados antes de hacer cualquier otra cosa y eso significa que el método PostConstruct a continuación siempre se llama antes cualquier cosa puede acceder al StatisticLogger algo como esto

    @Component public class DaoSetterService {

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

    }

  3. En lugar de utilizar StatisticLogger como clase estática, simplemente lo uso como StatisticLogger.getInstance () y puedo acceder a todos los métodos dentro de él