Автоматическая проверка условий в методах класса Java
Быстрый ответ
Сложность этой задачи можно обойти с помощью Аспектно-ориентированного программирования (AOP) с применением AspectJ. С его помощью код можно вставлять автоматически перед исполнением методов в классе. Пример использования выглядит так:
@Aspect
public class ВашиДействияAspect {
@Before("execution(* ВашЦелевойКласс.*(..))")
public void сделатьПредварительноКод() {
// Код, который будет работать перед каждым методом в классе
System.out.println("Привет, это выполнено перед методом.");
}
}
Связывание вашего аспекта с классом обеспечивает автоматическую реализацию выбранных вами действий перед каждым методом.
Динамическая предобработка с помощью java.lang.reflect.Proxy
Если вам нужно внедрить функционал незаметно, то java.lang.reflect.Proxy
может помочь осуществить задуманное без вмешательства в основную логику.
Взглянем поближе на InvocationHandler:
public class МойInvocationHandler implements InvocationHandler {
private final Object target;
public МойInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (!method.isAnnotationPresent(НеSuperSpy.class)) {
System.out.println("Секретный блок кода перед методом.");
}
// Исполнение основной логики метода
return method.invoke(target, args);
}
}
Создайте прокси для вашего интерфейса с помощью Proxy.newProxyInstance
:
YourInterface proxy = (YourInterface) Proxy.newProxyInstance(
ВашКласс.class.getClassLoader(),
new Class<?>[]{YourInterface.class},
new МойInvocationHandler(new ВашКласс())
);
Использование аннотации @НеSuperSpy
позволяет отключить выполнение кода:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface НеSuperSpy { }
Делаем код DRY
Необходимость ведения одной и той же последовательности кода отпадает – следующие подходы сделают ваш код DRY и избавят от повторения.
Помните о производительности
Такое применение рефлексии и проксирования может отрицательно сказаться на производительности, поэтому стоит применять эти подходы осмотрительно.
Визуализация
Для углубления понимания визуализируем процесс предварительного выполнения кода. Мы вновь обращаемся к аналогии с конвейером.
[💼 Методы класса 💼]
Каждый вызов метода проходит через конвейер:
Старт конвейера: 🔄 Предварительный блок кода
Мы можем отследить путешествие каждого метода через начальный этап:
🔄 → 💼 method1()
🔄 → 💼 method2()
🔄 → 💼 method3()
Это как проверка перед полетом: блок кода выполняется перед основной частью метода.
Изменяем поведение методов без дублирования
Чтобы изменить поведение метода без дублирования кода, воспользуйтесь Шаблоном стратегии или Шаблоном состояния.
Автоматизация создания кода
Если вам нужно сократить время на рутинное написание кода, обрататегь к генераторам кода и шаблонизаторам.
Полезные материалы
- Аспектно-ориентированное программирование с Spring – обзор АОП в Spring для управления функциональностью.
- Byte Buddy – Генерация кода во время выполнения для JVM – как генерировать байт-код на лету.
- Использование Java Reflection – отличное пособие от Oracle об использовании API рефлексии в Java.
- Стандартные аннотации (Java™ Tutorials) – всё о аннотациях и создании кода.
- Обсуждение на StackOverflow: Как использовать AOP в PHP – интересное обсуждение АОП в контексте PHP.