2

Springによってクラスに注入されるオブジェクトがあります(気になる場合はJdbcCursorItemReader )。

それは5つのインターフェースを実装し、そのうちの2つは私が気にしています(ItemReader、ItemStream)。クラスをどちらかにコーディングすると、Spring Dynamic Proxyが適切に挿入され、その上でメソッドを呼び出すことができます。

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

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

((ItemStream))blah.close();

かっこいい、両方のクラスのメソッドにアクセスできます。しかし、私はキャスティングのファンではなく、それを行うためのより良いスプリングマジックの方法がどこにあるべきかを知っています。私が考えた方法は、両方を組み合わせたインターフェイスを作成することでした。

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

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

タイプ[$Proxy0実装org.springframework.beans.factory.InitializingBean、org.springframework.batch.item.ItemReader、org.springframework.batch.item.ItemStream、org.springframework.aop.scope.ScopedObjectのプロパティ値の変換に失敗しました、org.springframework.aop.framework.AopInfrastructureBean、org.springframework.aop.SpringProxy、org.springframework.aop.framework.Advised]プロパティ'itemReader'に必要なタイプ[blah.IStreamingItemReader]に; ネストされた例外はjava.lang.IllegalArgumentExceptionです。タイプ[$Proxy0の値を変換できません。org.springframework.beans.factory.InitializingBean、org.springframework.batch.item.ItemReader、org.springframework.batch.item.ItemStream、orgを実装しています。 springframework.aop.scope.ScopedObject、org.springframework.aop.framework.AopInfrastructureBean、org.springframework.aop.SpringProxy、org。

私の目を引いた のは、一致するエディターや変換戦略が見つからなかったことです。

SpringがJdbcCursorItemReaderを見つけたときに、 IStreamingItemReaderのプロキシを作成するように教える方法はありますか?

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

4

3 に答える 3

3

簡単な方法:可能であれば、実装クラスに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());
    }
}
于 2010-11-18T20:39:05.127 に答える
1

オプション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();
于 2010-11-18T20:46:36.330 に答える
1

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

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(); 
于 2010-11-18T20:50:39.183 に答える