Регистрация 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");
}
}
Что имеет смысл и почему?
Ответы
Ответ 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.
}
}