Java 7 - оформление пользовательского метода без делегирования по умолчанию всех других методов

Я хотел бы украсить интерфейс PreparedStatement, чтобы пользователь мог закрыть его (просто пример).

Это означает, что я хочу украсить существующий экземпляр PreparedStatement, таким образом, вызывая другой код, когда close() вызывается.

Для этого мне нужно по умолчанию реализовать все десятки методов PreparedStatement Декоратор просто для делегирования вызовов внутреннему объекту, как это сделано здесь. Недостатком является то, что это просто много работы и кода с небольшой добавленной стоимостью.

Другой вариант - попытаться использовать Java Proxy и InvocationHandler, чтобы обеспечить реализацию по умолчанию, которая выполняет делегирование для всех методов в одном методе. Если пользовательский метод существует, InvocationHandler направляет вызов к нему. Смотрите пример здесь. Проблема с этим решением заключается в том, что пользовательский метод не может быть помечен как @Overrideи его подпись не может быть проверена на правильность, так как это потребует рефератаPreparedStatement, который Прокси не сможет создать.

Итак, это можно сделать?Как?

* Должен быть в состоянии реализовать с использованием Java 7 max, но не стесняйтесь предоставлять ответы на Java 8.

3 ответа

Насколько я понял вы хотите предоставить интерфейсу PreparedStatement конкретную реализацию. Единственный способ, о котором я могу думать, - это создание абстрактного класса, реализующего интерфейс. При этом вам не нужно реализовывать все методы интерфейса, и вы получите желаемую реализацию.

Я бы попробовал что-то вроде этого:

public abstract class MyPreparedStatement implements PreparedStatement {

@Override
public void close() throws SQLException {
    System.out.println("Closing");
}

public static void main(String[] args) throws SQLException {
    Connection con = null;
    MyPreparedStatement statement = (MyPreparedStatement) con.prepareStatement("sql");
}
}

Можете ли вы объяснить более четко, что Proxy решение отсутствует? Рассмотрим что-то вроде этого, которое опирается на "крючок" AOP-esque:

final PreparedStatement original = ...;
final InvocationHandler delegator = new InvocationHandler() {

  void onClose() {
    /* do stuff */
  }

  Object invoke(final Object proxy, final Method method, final Object[] args) {
    if (method.getName().equals("close")) {
      onClose();
    }

    return method.invoke(original, args);
  }
};
final PreparedStatement wrapped = (PreparedStatement) Proxy.newProxyInstance(this.getClass().getClassLoader(),
    new Class<?>[] { PreparedStatement.class }, delegator);

Если у вас нет доступа к методам для обычного наследования, вы можете выполнить то, что вы пытаетесь сделать, с помощью Aspect-Oriented Programming, используя AspectJ или функциональность аспекта Spring Framework, чтобы дать совет о желаемых методах.,

Простой аспект в основном сводится к:

@Aspect
public class MyAspect {

    @Pointcut("execution(* *(..))") //Replace expression with target method; this example 
    //will hit literally every method ever.
    public void targetmethod() {}; //Intentionally blank.
    //AspectJ uses byte code manipulation (or "black magic voodoo", if you 
    // will) to make this method a surrogate for any real one that matches the pointcut

    @Before("targetmethod()") //Or @After, or @Around, etc...
    public void doStuff() throws Throwable {
        //Put your code here
    }
}

Как только вы соберете свои аспекты вместе, добавьте их в свой aop.xml и сплетите свои аспекты (вы можете сделать это во время компиляции с соответствующей конфигурацией менеджера сборки или во время выполнения, запустив aspectjweaver с java -javaagent:/path/to/aspectjweaver.jar).

Это, однако, сопровождается отказом от ответственности: выполнение таких вещей с классами java.* Позволяет вам ломать вещи новыми и интересными способами со всеми вводимыми вами побочными эффектами (на самом деле AspectJWeaver отказывается вплетать классы java.* по умолчанию, хотя вы можете изменить эту настройку). Будьте очень осведомлены о том, что вы делаете, и используйте свои аспекты и разумные методы с умом.

Другие вопросы по тегам