2010-11-18 4 views
2

J'ai un objet qui est injecté dans ma classe au printemps (JdbcCursorItemReader si vous vous en souciez).Comment avoir un proxy dynamique Spring avec 2 interfaces?

Il implémente 5 interfaces dont deux sont importantes (ItemReader, ItemStream). Si je code ma classe à l'un ou l'autre, le proxy dynamique de printemps se correctement injecté et je peux appeler des méthodes sur ce

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

Cool, qui fonctionne comme prévu. Je peux aussi jeter un ItemStream si je veux faire quelque chose basé sur l'interface ItemStream:

((ItemStream))blah.close(); 

Cool, qui me permet de méthodes d'accès des deux classes. Cependant, je ne suis pas un fan de casting, et je sais où doit être un meilleur moyen de le faire. La façon dont je pensais était de faire une interface qui combine à la fois:

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

Cela permet mon utilisation de code à la fois ... mais l'injection de proxy échoue on pouvait s'y attendre.

a échoué à convertir la valeur de propriété de type [Proxy0 $ mise en œuvre 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] type requis [blah.IStreamingItemReader] pour propriété 'itemReader'; imbriqué exception est java.lang.IllegalArgumentException: Impossible de convertir la valeur de type [Proxy0 $ mise en œuvre 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] au type requis [blah.IStreamingItemReader ] pour propriété 'itemReader': pas éditeurs correspondant ou d'une stratégie de conversion trouvé

La partie qui a obtenu mon oeil était pas les éditeurs correspondant ou stratégie de conversion trouvé

Y at-il un moyen d'enseigner printemps quand il voit un JdbcCursorItemReader, pour faire une procuration d'un IStreamingItemReader?

Je me rends compte que je pouvais résoudre ce problème avec Cglib et proxys de classe ... mais si je pouvais garder cela comme un proxy d'interface dynamique, je serais plus heureux ...

Répondre

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

Puis:

private ItemAccessor accessor; 

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

Manière simple: si possible, faites votre implémentant la classe implémenter votre interface d'union au lieu des deux interfaces séparées.

manière moins claire, mais ne pas introduire des classes addtional (besoins génériques):

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

Une autre option avec les génériques (la plupart du temps comme un exercice théorique), ne nécessite pas de champs en double, mais nécessite un objet support:

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(); 
Questions connexes