1

カスタムで閉じるために、インターフェイスPreparedStatementを装飾したいと思います(単なる例です)。

PreparedStatementこれは、 の既存のインスタンスをデコレートして、 が呼び出されているときに他のコードを呼び出したいことを意味しclose()ます。

そのためには、ここで行われたように、内部オブジェクトへの呼び出しを委任するためだけに、デコレーターの数十のメソッドすべてをデフォルトで実装する必要があります。欠点は、多くの作業とコードに付加価値がほとんどないことです。PreparedStatement

もう 1 つのオプションは、Java のProxy と InvocationHandlerを使用して、単一のメソッドですべてのメソッドのデリゲートを行うデフォルトの実装を提供することです。カスタム メソッドが存在する場合、InvocationHandlerはそのメソッドに呼び出しを送信します。ここで例を参照してください。このソリューションの問題は、カスタム メソッドを as としてマークできず、その署名が正しいかどうかをチェックできないことです。これは、プロキシがインスタンス化できない@Overrideabstract が必要になるためです。PreparedStatement

それで、これはできますか?どのように?

* Java 7 max を使用して実装できる必要がありますが、Java 8 の回答を自由に提供してください。

4

3 に答える 3

0

私が理解している限りでは、インターフェース 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");
}
}
于 2016-06-27T13:26:12.657 に答える
0

Proxyソリューションに欠けているものをより明確に説明できますか? AOP 風の「フック」に依存する、次のようなものを検討してください。

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);
于 2016-06-28T16:21:45.053 に答える
-1

通常の継承を行うためにメソッドにアクセスできない場合は、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 に追加し、アスペクトを織ります (これは、適切なビルド マネージャー構成を使用してコンパイル時に行うか、実行時に を使用してspectjweaver を実行することで行うことができますjava -javaagent:/path/to/aspectjweaver.jar)。

ただし、これには免責事項があります。Java.* クラスに対してこのようなことを行うと、導入しているすべての副作用を使用して、新しい興味深い方法で物事を壊すことができます (実際、AspectJWeaver は、Java.* クラスへの織り込みを拒否します)。デフォルトですが、その設定をオーバーライドできます)。自分が何をしているのかを十分に認識し、アスペクトとアスペクト方式を賢く使用してください。

于 2016-06-27T13:53:19.863 に答える