spring cloud
@autowired en clases estáticas (3)
El cableado automático clásico probablemente no funcione, porque una clase estática no es un Bean y, por lo tanto, no puede ser administrada por Spring. Hay formas de solucionar 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 utilice métodos estáticos, use servicios que inyecte donde los necesite. Si usas Spring, bien podrías usarlo correctamente. La inyección de dependencia es una técnica orientada a objetos, y solo tiene sentido si realmente abrazas la POO.
Este es un proyecto de Spring MVC con Hibernate. Estoy tratando de crear una clase de registrador que sea responsable de ingresar los registros en la base de datos. Otras clases simplemente llaman a los métodos adecuados 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 objeto dao autoalimentado.
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);
}
}
¿Cómo hacerlo bien? ¿Qué debo hacer para no hacer nula el objeto dao? Sé que podría pasarlo como un parámetro del método, pero eso no es muy bueno. Supongo que el cableado automático no puede funcionar en objetos estáticos, ya que están creados para que el mecanismo de inicio automático aún no se haya creado.
No puedes @Autowired
un campo estático. Pero hay una habilidad difícil para lidiar 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 asigna el valor al archivo estático cuando se construye el objeto. Por cierto, el objeto StatisticLogger
debe ser administrado por Spring.
Sé que esta es una pregunta antigua, pero solo quería compartir lo que hice, la solución de @Weibo Li está bien, pero el problema es que genera una alerta crítica de Sonar sobre la asignación de una variable no estática a una variable estática.
La forma en que lo resolví sin alertas de sonar es la siguiente
Cambio el StatisticLogger a la clase singlton (ya no estática) como esta
clase pública 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<String, Object> parameters){ ExceptionLogBean elb=new ExceptionLogBean(); elb.setStuntDescription(e); elb.setSourcePage(page); elb.setParameters(parameters); if(dao!=null){ dao.saveOrUpdateEntity(elb); }
}
Creé un servicio (o Componente) que autoriza el servicio que quiero y lo configuro en la clase de singlton. Esto es seguro ya que en la primavera inicializará todos los beans administrados antes de hacer cualquier otra cosa y eso significa que siempre se llama al método PostConstruct a continuación. 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); }
}
En lugar de usar StatisticLogger como clase estática, solo lo uso como StatisticLogger.getInstance () y puedo acceder a todos los métodos que contiene.