Как иметь Spring динамический прокси с 2 интерфейсами? - PullRequest
2 голосов
/ 18 ноября 2010

У меня есть объект, который внедряется в мой класс Spring ( JdbcCursorItemReader , если вам важно).

Он реализует 5 интерфейсов, два из которых мне не безразличны (ItemReader, ItemStream),Если я закодирую свой класс одним или другим, динамический прокси-сервер пружины будет правильно введен, и я смогу вызывать методы для него

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

Cool, который работает, как и ожидалось.Я также могу привести его к ItemStream, если я хочу сделать что-то на основе интерфейса ItemStream:

((ItemStream))blah.close();

Круто, что позволяет мне получать доступ к методам обоих классов.Тем не менее, я не фанат кастинга, и знаю, где должен быть лучший способ сделать это в Spring Magic.Я подумал о том, чтобы создать интерфейс, который бы сочетал в себе оба:

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. oropg.ject.Obg.springframework.aop.framework.AopInfrastructureBean, org.springframework.aop.SpringProxy, org.springframework.aop.framework.Advised] в обязательный тип [blah.IStreamingItemReader] для свойства itemReader;вложенным исключением является java.lang.IllegalArgumentException: невозможно преобразовать значение типа [$ Proxy0, реализующее org.springframework.beans.factory.InitializingBean, org.springframework.batch.item.ItemReader, org.springframework.batch.itemg.tem.Item.springframework.aop.scope.ScopedObject, org.springframework.aop.framework.AopInfrastructureBean, org.springframework.aop.SpringProxy, org.springframework.aop.framework.Advised] для требуемого свойства [blah.Reader] дляне найдено ни одного подходящего редактора или стратегии конверсии

Часть, которая попалась мне на глаза, была не найдено ни одного подходящего редактора или стратегии конверсии

Есть ли способ научить Spring, когдаон видит JdbcCursorItemReader , чтобы создать прокси для IStreamingItemReader ?

Я понимаю, что мог бы это исправить с помощью CGLib и прокси на основе классов ... но если бы я мог сохранить это как прокси динамического интерфейса, я был бы счастлив ...

Ответы [ 3 ]

3 голосов
/ 18 ноября 2010

Простой способ: если возможно, заставьте ваш реализующий класс реализовать ваш интерфейс объединения вместо двух отдельных интерфейсов.

Менее понятный способ, но не вводит дополнительные классы (нужны обобщенные значения):

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 голос
/ 18 ноября 2010

Еще один вариант с обобщениями (в основном в качестве теоретического упражнения), не требует дублирования полей, но требует объект-держатель:

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(); 
1 голос
/ 18 ноября 2010

Вариант 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();
...