@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);
}
}
Как это сделать правильно? Что я должен сделать, чтобы сделать dao object null?
Я знаю, что могу передать его как параметр метода, но это не очень хорошо.
Я предполагаю, что autowired не может работать на статических объектах, потому что они созданы для механизма автоподготовки до начала еще не созданы.
Ответы
Ответ 1
Нельзя @Autowired
статическое поле. Но есть сложный навык, чтобы справиться с этим:
@Component
public class StatisticLogger {
private static Dao dao;
@Autowired
private Dao dao0;
@PostConstruct
private void initStaticDao () {
dao = this.dao0;
}
}
В одном слове @Autowired
поле экземпляра и присвойте значение статическому файлу, когда ваш объект сконструирован. BTW, объект StatisticLogger
должен управляться также с помощью Spring.
Ответ 2
Классическое автосообщение, вероятно, не будет работать, потому что статический класс не является Bean и, следовательно, не может управляться с помощью Spring. Есть способы обойти это, например, используя factory-method
aproach в XML или загружая beans из контекста Spring в статическом блоке инициализатора, но я бы предложил изменить дизайн:
Не используйте статические методы, используйте службы, которые вы вводите там, где они вам нужны. Если вы используете Spring, вы можете использовать его правильно. Инъекция зависимостей - это объектно-ориентированная техника, и это имеет смысл только в том случае, если вы действительно используете ООП.
Ответ 3
Я знаю, что это старый вопрос, но просто хотел поделиться тем, что я сделал,
решение @Weibo Li в порядке, но проблема в том, что он вызывает критическое предупреждение сонара о назначении нестатической переменной статической переменной
способ, которым я разрешил его без предупреждений сонара, следующий
-
Я меняю StatisticLogger на класс singlton (больше не статический)
как это
публичный класс StatisticLogger { частный статический экземпляр StatisticLogger = 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
Это безопасно, поскольку в spring он будет инициализировать все управляемые beans, прежде чем делать что-либо еще, и это означает, что метод PostConstruct, указанный ниже, всегда вызывается, прежде чем что-либо сможет получить доступ к StatisticLogger
что-то вроде этого
@Component
открытый класс DaoSetterService {
@Autowired
private Dao dao0;
@PostConstruct
private void setDaoValue () {
StatisticLogger.getInstance().setDao(dao0);
}
}
-
Вместо использования StatisticLogger как статического класса я просто использую его как StatisticLogger.getInstance(), и я могу получить доступ ко всем методам внутри него