2016-06-27 6 views
1

decoratePreparedStatement私はカスタムを閉じるために(ちょっと例を挙げます)decorateです。Java 7 - カスタムメソッドデコレーション、デフォルト以外のすべてのメソッド、他の多くのメソッドを委任する

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

、私はhereをやっようにだけ、内部オブジェクトへの呼び出しを委任するPreparedStatementデコレータの方法の全てを実装デフォルトする必要があります。欠けているのは、付加価値の少ない仕事とコードだけです。

もう1つの方法は、単一のメソッドですべてのメソッドのデリゲートを行うデフォルトの実装を提供するために、JavaのProxy and InvocationHandlerを試してみることです。カスタムメソッドが存在する場合、InvocationHandlerは呼び出しを呼び出します。例hereを参照してください。 この解決方法の問題点は、カスタムメソッドに@Overrideというマークを付けることができず、プロキシがインスタンス化できないアブストラクトPreparedStatementが必要なため、その署名の正当性をチェックできないことです。

これはできますか?どうやって?

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

+0

:AOP風の「フック」に依存していますこのような何かを、考えてみましょう。 – PyThon

+0

Mockitoを使用できますか? –

+0

AOPを使用して機能を実現できます。しかし、1つの質問、なぜあなたは 'PreparedStatement'を装飾する必要がありますか? – Dimitri

答えて

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"); 
} 
} 
+2

私はあなたが 'Decorator'概念を見逃したと思います。私は受け取った 'PreparedStatement'のインスタンスを制御しません。私はちょうどそれを使用する方法を制御します。あなたが解決すると、ClassCastExceptionが発生します。 –

+0

はい、申し訳ありませんが、実際にそれを逃した。 – Ivo

-1

は、あなたがで何しようとしているものを達成することができますAspect Oriented Programming、AspectJまたはSpring Frameworkのアスペクト機能を利用して、あなたの望むメソッドに関するアドバイスを提供します。

簡単な側面は、基本的にダウンしています:あなたが一緒にあなたの側面を持っていたら、あなたのaop.xmlに追加

@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 
    } 
} 

とあなたの側面を織る(あなたが適切なビルド・マネージャー構成で、コンパイル時にこれを行うことができます、またはjava -javaagent:/path/to/aspectjweaver.jarでaspectjweaverを実行して実行時に)。

これは免責事項が付いていますが、このようなことをjava。*クラスにすると、あなたが導入しているすべての副作用で新しく面白い方法で物事を壊すことができます(実際にAspectJWeaverはjava 。*デフォルトでは、あなたはその設定を上書きすることができます)。あなたが何をしているのかをよく知り、あなたの側面と方法論的方法を賢明に使用してください。

+0

'@ Override'を使ったcloseメソッドの正確な署名はどこにありますか? –

+0

あなたはそのメソッドのポイントカットをどう求めるのですか?それはあなたの側面に触れさせたい方法に完全に依存します。 '' call(public java.sql.PreparedStatement + .close(..)) ""のようなものは、PreparedStatementまたはのサブクラスで 'close()'とマッチする必要があります。 [This AspectJ pointcut reference](https://eclipse.org/aspectj/doc/next/quick5.pdf)が役に立つかもしれません。 –

0

Proxyソリューションに欠けていることを明確に説明できますか?それはデコレータを書くためのメインキーですので、あなたはより多くのそれを説明してくださいすることができ、カスタム閉鎖とはどういう意味ですか

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); 
+0

議論されたメソッドがいくつかの引数を受け取ったとします。これで、カスタムメソッドをリフレクションで呼び出す必要があります(手動でargsを変換しないため)。つまり、コンパイル時には、誰もカスタムクローズメソッドを呼び出すことはありません。つまり、カスタムの「close」メソッドのシグネチャを変更できると誰かが考えることができるということです。私の目的は、カスタムメソッドを実際のインターフェース 'PreparedStatement'に、好ましくは' @ Override'によって保つことです。カスタムメソッドをインターフェイスに関連付けるもう1つの理由は、検索を行うときにカスタムメソッドを見つけさせることです。 –

+0

@ AlikElzin-kilaka次に明らかな解決策は、前に述べたように、委譲する 'PreparedStatementDecorator'を書くことです。必要最小限のオーバーヘッドですべてを達成します – oldrinb

関連する問題