2010-11-18 2 views
2

Ich habe ein Objekt, das von Spring (JdbcCursorItemReader, wenn Sie interessiert sind) in meine Klasse injiziert wird.Wie kann ein Spring Dynamic Proxy mit 2 Schnittstellen erstellt werden?

Es implementiert 5 Schnittstellen, von denen ich zwei (ItemReader, ItemStream) interessiert. Wenn ich meine Klasse zu dem einen oder anderen Code, wird die Feder dynamische Proxy richtig injiziert und ich kann

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

Cool, auf es Methoden aufrufen, die wie erwartet funktioniert. Ich kann es auch zu einer ItemStream werfen, wenn ich etwas auf dem ItemStream Schnittstelle basierte tun will:

((ItemStream))blah.close(); 

Cool, die mir Zugriffsmethoden beiden Klassen ermöglicht. Ich bin jedoch kein Fan von Casting und weiß, wo eine bessere Frühlingsmagie sein muss. Die Art, wie ich dachte, war eine Schnittstelle zu machen, die beide verbindet:

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

Auf diese Weise können meinen Code verwenden beide ... aber die Proxy-Injektion nicht vorhersagbar.

fehlgeschlagen Eigenschaftswert von Typ [$ Proxy0 Umsetzung org.springframework.beans.factory.InitializingBean, org.springframework.batch.item.ItemReader, org.springframework.batch.item.ItemStream, org zu konvertieren .springframework.aop.scope.ScopedObject, org.springframework.aop.framework.AopInfrastructureBean, org.springframework.aop.SpringProxy, org.springframework.aop.framework.Advised] auf die gewünschte Art [blah.IStreamingItemReader] für Eigenschaft 'itemReader'; verschachtelte Ausnahme ist java.lang.IllegalArgumentException: Wert kann nicht vom Typ umwandeln [$ Proxy0 Implementierung 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] zum erforderlichen Typ [blah.IStreamingItemReader ] für Eigenschaft 'itemReader': keine passende Strategie Editoren oder Umwandlung gefunden

Der Teil, der mein Auge bekam, war keine Editoren oder Umstellungsstrategie, gefunden

Gibt es eine Möglichkeit Frühling zu lehren, wenn es sich um eine sieht JdbcCursorItemReader, um einen Proxy eines IStreamingItemReader?

Ich weiß, ich könnte dieses Problem beheben mit CGLIB und Klasse basiert Proxies ... aber wenn ich dies als eine dynamische Schnittstelle Proxy halten könnte, wäre ich glücklicher sein ...

Antwort

1

Option 1

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

Option 2

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

Dann:

private ItemAccessor accessor; 

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

Einfache Möglichkeit: Wenn möglich, machen Sie Ihre Implementierungsklasse implementieren Sie Ihre Union-Schnittstelle anstelle der zwei separaten Schnittstellen.

Weniger klar Art und Weise, aber führt keine addtional Klassen (benötigt Generika):

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()); 
    } 
} 
1

Noch eine weitere Option mit Generika (meist als theoretische Übung), erfordert nicht dupliziert Felder, erfordert aber eine Halterobjekt:

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(); 
Verwandte Themen