【问题标题】:How to have a Spring dynamic proxy with 2 interfaces?如何拥有具有 2 个接口的 Spring 动态代理?
【发布时间】:2010-11-18 20:16:46
【问题描述】:

我有一个由 Spring 注入到我的班级的对象(JdbcCursorItemReader,如果你关心的话)。

它实现了 5 个接口,其中两个我关心(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.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] 到所需类型 [blah.IStreamingItemReader] 为 属性'itemReader';嵌套的 例外是 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.springframework.aop.framework.Advised] 到所需类型 [blah.IStreamingItemReader] 为 属性“itemReader”:没有匹配 找到编辑器或转换策略

引起我注意的部分是 未找到匹配的编辑器或转化策略

有没有办法在 Spring 看到 JdbcCursorItemReader 时教它,以制作 IStreamingItemReader 的代理?

我意识到我可以使用 CGLib 和基于类的代理来解决这个问题...但是如果我可以将其保留为动态接口代理,我会更开心...

【问题讨论】:

    标签: java spring proxy dynamic-proxy


    【解决方案1】:

    简单的方法:如果可能的话,让你的实现类实现你的联合接口,而不是两个单独的接口。

    不太清楚的方法,但没有引入额外的类(需要泛型):

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

    【讨论】:

      【解决方案2】:

      选项 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();
      

      【讨论】:

        【解决方案3】:

        另一个使用泛型的选项(主要作为理论练习),不需要重复的字段,但需要一个持有者对象:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多