У меня есть пара классов, которые реализуют конкретный interface
, что-то вроде следующего (это, очевидно, очень упрощенная версия, но суть вопроса):
public interface Talk {
void sayIt();
}
Первая реализация Talk
:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SayHello implements Talk {
static final Logger LOG = LoggerFactory.getLogger(SayHello.class);
public SayHello() {}
public void sayIt() {
System.out.println("Hello");
}
}
Вторая реализация Talk
:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SayGoodbye implements Talk {
static final Logger LOG = LoggerFactory.getLogger(SayHello.class);
public SayGoodbye() {}
public void sayIt() {
System.out.println("GoodBye");
}
}
Теперь в методе sayIt()
я хочу реализовать ведение журнала уровня трассировки и некоторые таймеры выполнения метода, которыеЯ могу просто сделать что-то следующим образом:
public void sayIt() {
long startTime = System.currentTimeMillis();
LOG.trace("Executing sayIT for implementation {} , start time at {}.", this.getClass().getSimpleName(), startTime);
System.out.println("Hello");
LOG.trace("sayIT for implementation {} took {} milliseconds to execute.", this.getClass().getSimpleName(), System.currentTimeMillis() - startTime);
}
Проблема в том, что мне нужно было бы скопировать и вставить это в каждую реализацию метода sayIt()
для каждой class
, которая реализует Talk
интерфейс, и я действительно не хочу этого делать, потому что ...
- Это создает много дублирования.
- С большим количеством реализаций вы начинаете испытывать головную боль при обслуживании, особенно когда вырешите немного изменить реализацию.
- Я ленивый и хотел бы писать как можно меньше кода, используя как можно больше.
Итак, вот вопрос .... как бы я достиг целиписать один раз, использовать несколько раз? Синхронизация методов - это одно из приложений, но я действительно хочу иметь возможность «вставлять» код в начало и конец метода.
Я действительно ищу рабочий пример (не просто ссылку на дополнительные ссылки) чего-то, что может работать (я предполагаю что-то вроде AspectJ ,но у меня были бесконечные хлопоты, пытаясь заставить его работать с Gradle ... возможно, просто попытался реализовать Maven)
О, да, я мог бы вместо добавления кода в sayIt()
добавить его вкод, вызывающий sayIt()
, например:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class SomeOtherClass {
static final Logger LOG = LoggerFactory.getLogger(SomeOtherClass.class);
public SomeOtherClass() {}
public void letsHaveAConversation() {
List<Talk> talks = new ArrayList<>();
talks.add(new SayHello());
talks.add(new SayGoodbye());
for (Talk talking : talks) {
long startTime = System.currentTimeMillis();
LOG.trace("Executing sayIT for implementation {} , start time at {}.", talking.getClass().getSimpleName(), startTime);
talking.sayIt();
LOG.trace("sayIT for implementation {} took {} milliseconds to execute.", talking.getClass().getSimpleName(), System.currentTimeMillis() - startTime);
}
}
}
Это будет работать, но не в том случае, если у меня несколько мест, откуда вызывается sayIt()
.