@autowired в статических классах - программирование
Подтвердить что ты не робот

@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 не может работать на статических объектах, потому что они созданы для механизма автоподготовки до начала еще не созданы.

4b9b3361

Ответ 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(), и я могу получить доступ ко всем методам внутри него