Ответ
Да, можно, но не напрямую через стандартный java.lang.reflect.Proxy. Для проксирования конкретных классов (а не интерфейсов) требуются библиотеки, такие как CGLIB или ByteBuddy, которые генерируют байткод во время выполнения.
Как это работает (на примере CGLIB):
- Создается подкласс целевого класса
A. - Вызовы методов этого подкласса перехватываются callback-ом (например, реализацией
MethodInterceptor), который определен в вашем классеB. - В этом callback-е вы можете добавить логику "до", "после" или вместо вызова оригинального метода.
Пример с CGLIB:
import net.sf.cglib.proxy.*;
// Целевой класс
class ServiceA {
public void process() {
System.out.println("Оригинальная логика ServiceA");
}
}
// Обработчик (ваш класс B)
class LoggingInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("[Прокси] Вызов метода: " + method.getName());
Object result = proxy.invokeSuper(obj, args); // Вызов оригинального метода
System.out.println("[Прокси] Метод завершен.");
return result;
}
}
// Создание прокси
public class Demo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ServiceA.class); // Указываем класс для проксирования
enhancer.setCallback(new LoggingInterceptor()); // Устанавливаем наш обработчик
ServiceA proxy = (ServiceA) enhancer.create(); // Создаем экземпляр прокси
proxy.process(); // Вызов будет перехвачен
// Вывод:
// [Прокси] Вызов метода: process
// Оригинальная логика ServiceA
// [Прокси] Метод завершен.
}
}
Важные ограничения:
- Нельзя проксировать
finalклассы илиfinalметоды. - Конструктор родительского класса вызывается дважды (это особенность CGLIB).
- Требует добавления внешней библиотеки в зависимости проекта.