Подтвердить что ты не робот

Регистрация Java с абстрактными классами

Я работаю над проектом, и в настоящее время я работаю над выполнением некоторых протоколирования с помощью log4j, и мне было любопытно, как я должен заниматься внедрением журналов. Две реализации, которые я пинаю, следующие:

Первый вариант

Использовать одиночный журнал из суперкласса для этого класса и всех подклассов:

public abstract class AbstractFoo {
    protected static Log LOG = LogFactory.getLog(AbstractFoo.class);

    ...
}

public class Foo extends AbstractFoo {
    public void someMethod() {
        LOG.info("Using abstract log");
    }
}

Второй вариант

Используйте отдельные журналы для каждого класса, супер и субмарины:

public abstract class AbstractFoo {
    private static Log LOG = LogFactory.getLog(AbstractFoo.class);

    ...
}

public class Foo extends AbstractFoo {
    private static Log LOG = LogFactory.getLog(Foo.class);        

    public void someMethod() {
        LOG.info("Using own log");
    }
}

Что имеет смысл и почему?

4b9b3361

Ответ 1

Я бы тоже этого не делал. Вместо этого я хотел бы использовать правильный класс в обоих случаях.

public abstract class AbstractFoo {
    protected final Log log = LogFactory.getLog(getClass());

    ...
}

public class Foo extends AbstractFoo {
    public void someMethod() {
        log.info("Using abstract log");
    }
}

Если вы не выполняете много протоколирования (что в любом случае является хорошей идеей), вы можете использовать метод.

public abstract class AbstractFoo {
    protected Log log() { return LogFactory.getLog(getClass()); }

    ...
}

Если есть класс, который вызывает это много, вы можете переопределить его, чтобы предоставить вам кешированный экземпляр.

Ответ 2

Это мое решение (окончательный статический логгер):

public abstract class AbstractFoo {
     protected Log getLogger();
     public doSomething() {
          getLogger().info("log something");
     }
}

public class Foo extends AbstractFoo {
    private static final Log log = Log.getLogger(Foo.class);

    protected Log getLogger() {
         return log;
    }
    public doSomethingElse() {
          log.info("log somethingElse");
    }
}

Ответ 3

Оба имеют смысл. Это зависит от вашего приложения.

Я думаю, что чаще всего практика заключается в том, чтобы иметь частный регистратор для каждого класса. Это позволяет настраивать ведение журнала как для каждого класса, так и для каждого пакета. Помните, что AbstractFoo и Foo могут принадлежать к разным пакетам и, вероятно, вы хотите видеть журналы только из Foo.

Кроме того, всегда думайте дважды, если хотите написать поле protected. Это не полностью запрещено, но хорошо известная плохая практика. Это делает ваш код менее читаемым и его трудно поддерживать.

Ответ 4

Если вы создадите регистратор в абстрактном классе, все журналы будут отмечены как созданные из AbstractFoo. Если вы хотите/должны видеть журналы, отмеченные дочерним классом, из которых произошел журнал, создайте регистраторы для дочерних классов.

Ответ 5

То же самое можно достичь, играя с конструкторами. Добавьте регистратор на уровне класса Base и установите его из каждого класса Derived, используя super(). Существует код:

public abstract class AbstractFoo {

    protected Log log;  // base abstract class has a Log object.

    public AbstractFoo(Log logger) {   // parameterized constructor for logger, to be used by the derived class.
        this.log = logger;
    }

    public doSomething() {        // common method for all the derived classes.
      log.info("log something");
    }
    // rest of business logic.
}

public class Foo extends AbstractFoo {

    public Foo(){
        super(LogFactory.getLog(AbstractFoo.class));
    }

    public void someMethod() {
        log.info("Using own log");     // this uses its own logger.
    }
}