@autowired в статических классах
Это проект Spring MVC с Hibernate. Я пытаюсь создать класс Logger, который отвечает за ввод журналов в базу данных. Другие классы просто вызывают правильные методы с некоторыми атрибутами, и этот класс должен делать всю магию. По своей природе это должен быть класс со статическими методами, но это вызывает проблемы с автоповерхностью объекта 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);
}
}
Как сделать это правильно? Что я должен сделать, чтобы сделать объект Дао нулевым? Я знаю, что могу передать его как параметр метода, но это не очень хорошо. Я предполагаю, что autowired не может работать на статических объектах, потому что они созданы раньше, чтобы механизм autowiering еще не был создан.
5 ответов
Ты не можешь @Autowired
статическое поле. Но есть хитрый навык, чтобы справиться с этим:
@Component
public class StatisticLogger {
private static Dao dao;
@Autowired
private Dao dao0;
@PostConstruct
private void initStaticDao () {
dao = this.dao0;
}
}
Одним словом, @Autowired
поле экземпляра и присвойте значение статическому полю при создании объекта. Кстати, StatisticLogger
Spring должен также управлять объектом.
Классическая автопроводка, вероятно, не будет работать, потому что статический класс не является Бином и, следовательно, не может управляться Spring. Есть способы обойти это, например, с помощью factory-method
Подход в XML или путем загрузки bean-компонентов из контекста Spring в блок статического инициализатора, но я бы предложил изменить ваш дизайн:
Не используйте статические методы, используйте сервисы, которые вы внедряете там, где они вам нужны. Если вы используете Spring, вы можете использовать его правильно. Внедрение зависимостей - это объектно-ориентированная техника, и она имеет смысл только в том случае, если вы действительно используете ООП.
Я знаю, что это старый вопрос, но я просто хотел поделиться тем, что я сделал, решение @Weibo Li в порядке, но проблема, которую он вызывает, Sonar. Критическое предупреждение о назначении не статической переменной статической переменной.
способ, которым я решил это без предупреждений сонара, является следующим
Я изменяю StatisticLogger на класс singlton (больше не статический), как это
открытый класс StatisticLogger {частный статический StatisticLogger instance = null; частный дао дао;
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); }
}
Я создал сервис (или Компонент), который автоматически связывает сервис, который я хочу, и установил его в классе singlton. Это безопасно, поскольку весной он инициализирует все управляемые bean-компоненты перед выполнением чего-либо еще, и это означает, что метод PostConstruct ниже всегда вызывается перед все может получить доступ к StatisticLogger что-то вроде этого
@Component открытый класс DaoSetterService {
@Autowired private Dao dao0; @PostConstruct private void setDaoValue () { StatisticLogger.getInstance().setDao(dao0); }
}
Вместо использования StatisticLogger в качестве статического класса, я просто использую его как StatisticLogger.getInstance(), и я могу получить доступ ко всем методам внутри него.
Может быть слишком поздно давать ответ на этот вопрос, особенно когда на вопрос уже есть принятый ответ. Но это может помочь другим, если они столкнутся с той же проблемой.
внутри класса создайте экземплярDao
услуга.
public static Dao daoService = new Dao();
затем автоматически подключите экземпляр службы через конструкторStatisticLogger
сорт.
@Autowired
public functionName(Dao daoService0) {
this.daoService = daoService0;
}
//use this service as usual in static class
daoService.fun();
Я думаю, что это самое простое решение проблемы.
Вы можете передать DAO StatisticLogger
откуда вы это называете.
public static void AddLoginEvent(LogStatisticBean user, DAO dao){
dao.callMethod();
}