2 つのインターフェイスを持つ Spring 動的プロキシを使用するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/4219143

質問

Spring によってクラスに挿入されるオブジェクトがあります (JdbcCursorItemReader もし気にするなら)。

これは 5 つのインターフェイスを実装しており、そのうちの 2 つ (ItemReader、ItemStream) に注目します。クラスをどちらか一方にコーディングすると、Spring 動的プロキシが適切に挿入され、そのプロキシ上でメソッドを呼び出すことができます。

private ItemReader blah;
public void setItemReader( blah ) { this.blah = blah };

すごいですね、期待どおりに機能します。また、ItemStream インターフェイスに基づいて何かを実行したい場合は、ItemStream にキャストすることもできます。

((ItemStream))blah.close();

素晴らしいですね、これで両方のクラスのメソッドにアクセスできるようになります。しかし、私はキャスティングのファンではないので、Spring Magic のより良い方法がどこにあるのかを知っています。私が考えた方法は、次の両方を組み合わせたインターフェイスを作成することでした。

public interface IStreamingItemReader<T> extends ItemReader<T>, ItemStream {
}

これにより、コードで両方を使用できるようになります...しかし、プロキシ インジェクションは予想通り失敗します。

タイプのプロパティ値を変換できませんでした[$ proxy0 org.springframework.beans.factory.factory.initializingbean、org.springframework.batch.item.itemframework.batch.item.itemstream、org.springframework.aop.scope.scopedobjectobjedobject.scope.scopedobeje 、org.springframework.aop.framework.aopinfrastructurebean、org.springframework.aop.springproxy、org.springframework.aop.framework.advised]必要なタイプ[blah.istemingitemreaderネストされた例外はjava.lang.illegalargumentexceptionです。$ proxy0実装org.springframework.beans.factory.initializingbean、org.springframework.batch.item.itemreader、org.springframework.item.itemstream、org.springframework.aop.scope.scope.scopedobject、org、org、org.scopedobject、org、org.scopedobject.scopedobject、org、org、org.scopedobums、org、org、org.scopedobums、org、org、org。 .springframework.aop.framework.aopinfrastructurebean、org.springframework.aop.springproxy、org.springframework.aop.framework.advised]必要なタイプ[blah.istreamingitemreader] for property 'Itemreader':一致する編集者や変換戦略は見つかりませんでした

私の目を引いた部分は、一致するエディターまたは変換戦略が見つかりませんでした

を見たときに Spring に教える方法はありますか? JdbcCursorItemReader, のプロキシを作成します。 IStreamingItemReader?

CGLib とクラスベースのプロキシを使用してこれを修正できることに気づきました...しかし、これを動的インターフェイス プロキシとして維持できれば、もっと幸せになるでしょう...

役に立ちましたか?

解決

オプション1

private ItemReader blah;
private ItemStream blubb;
public void setItemReader( blah ) { this.blah = blah };
public void setItemStream( blubb ) { this.blubb = blubb };

オプション 2

class ItemAccessor {
 private ItemReader reader;
 private ItemStream stream;
 // Setter & co ...
}

それから:

private ItemAccessor accessor;

accessor.getReader().read();
accessor.getStream().stream();

他のヒント

簡単な方法:可能であれば、実装クラスに 2 つの別々のインターフェイスではなく、ユニオン インターフェイスを実装させてください。

それほど明確ではありませんが、追加のクラスを導入しません(ジェネリックが必要です)。

public interface A { }

public interface B { }

public class C implements A, B { }

public class D {
    private A a;
    private B b;

    public <T extends A & B> void setObject(T o) {
        this.a = o;
        this.b = o;
    }

    public static void main(String[] args) {
        D d = new D();
        d.setObject(new C());
    }
}

ジェネリックを使用したさらに別のオプション (主に理論的な演習として) では、フィールドの重複は必要ありませんが、ホルダー オブジェクトが必要です。

class ReaderStreamHolder<T extends ItemReader & ItemStream> {
    private final T target;
    public ReaderStreamHolder(T target) {
        this.target = target;
    }
    public T get() {
        return target;
    }
}

.

private ReaderStreamHolder<?> blah; 
public <T extends ItemReader & ItemStream> void setItemReader(T target) { 
    this.blah = new ReaderStreamHolder<T>(target)
};

.

blah.get().close(); 
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top