【问题标题】:Can I configure Orika to disregard return type of setter我可以将 Orika 配置为忽略 setter 的返回类型吗
【发布时间】:2021-09-13 16:56:42
【问题描述】:

由于从不相关的库进行版本升级,我们的 DTO 拥有流畅的设置器。基本上是一件好事,但现在 Orika 无法映射属性

public class DebugOrikaTest {

  @Test
  public void simpleToFluent() {
    final MapperFacade mapper = new ConfigurableMapper();
    final SimpleWithBoolean a = new SimpleWithBoolean();
    a.setFoo(Boolean.TRUE);
    a.setBar("foobar");
    final FluentWithBoolean b = new FluentWithBoolean();
   // act
    mapper.map(a, b);
    // assert
    Assertions.assertEquals("foobar", b.getBar());
    Assertions.assertTrue(b.isFoo());
  }

  @Test
  public void simpleToOther() {
    final MapperFacade mapper = new ConfigurableMapper();
    final SimpleWithBoolean a = new SimpleWithBoolean();
    a.setFoo(Boolean.TRUE);
    a.setBar("foobar");
    final OtherWithBoolean b = new OtherWithBoolean();
    // act
    mapper.map(a, b);
    // assert
    Assertions.assertEquals("foobar", b.getBar());
    Assertions.assertTrue(b.isFoo());
  }

  public static class SimpleWithBoolean {
    private Boolean foo;
    private String bar;

    public Boolean isFoo() {
      return foo;
    }

    public void setFoo(Boolean foo) {
      this.foo = foo;
    }

    public String getBar() {
      return bar;
    }

    public void setBar(String bar) {
      this.bar = bar;
    }
  }

  public static class FluentWithBoolean {
    private Boolean foo;
    private String bar;

    public Boolean isFoo() {
      return foo;
    }

    public FluentWithBoolean setFoo(Boolean foo) {
      this.foo = foo;
      return this;
    }

    public String getBar() {
      return bar;
    }

    public FluentWithBoolean setBar(String bar) {
      this.bar = bar;
      return this;
    }
  }

  public static class OtherWithBoolean {
    private Boolean foo;
    private String bar;

    public Boolean isFoo() {
      return foo;
    }

    public void setFoo(Boolean foo) {
      this.foo = foo;
    }

    public String getBar() {
      return bar;
    }

    public void setBar(String bar) {
      this.bar = bar;
    }
  }

}

simpleToOther 测试为绿色,但 simpleToFluent 失败。有没有办法配置 Orika 将标准 JavaBean setter 映射到 fluent setter?

【问题讨论】:

    标签: java mapping orika


    【解决方案1】:

    罪魁祸首(至少在 Orika 1.5.2 中)是使用 java.beans 的 IntrospectorPropertyResolver:

    BeanInfo beanInfo = Introspector.getBeanInfo(type);
    PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
    

    这将返回具有流畅设置器的属性。以下子类使用 Apache beanutils,它有一个FluentPropertyBeanIntrospector

    public class LenientIntrospectorPropertyResolver extends IntrospectorPropertyResolver {
    
      private boolean includeTransientFields;
    
      public LenientIntrospectorPropertyResolver(boolean includePublicFields) {
        super(includePublicFields);
      }
    
      public LenientIntrospectorPropertyResolver(boolean includePublicFields, boolean includeTransientFields) {
        super(includePublicFields, includeTransientFields);
        this.includeTransientFields = includeTransientFields;
      }
    
      public LenientIntrospectorPropertyResolver() {
      }
    
      @Override
      protected void collectProperties(Class<?> type, Type<?> referenceType, Map<String, Property> properties) {
        PropertyUtils.addBeanIntrospector(new FluentPropertyBeanIntrospector());
        final PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(type);
        for (final PropertyDescriptor pd : descriptors) {
          processPropertyDescriptor(type, referenceType, properties, pd);
        }
      }
    
      private void processPropertyDescriptor(Class<?> type, Type<?> referenceType, Map<String, Property> properties, PropertyDescriptor pd) {
        try {
          Method readMethod = PropertyUtils.getReadMethod(pd);
          if (readMethod == null && Boolean.class.equals(pd.getPropertyType())) {
            /*
             * Special handling for Boolean "is" read method; not strictly
             * compliant with the JavaBeans specification, but still very common
             */
            try {
              readMethod = type.getMethod("is" + capitalize(pd.getName()));
            } catch (NoSuchMethodException e) {
              readMethod = null;
            }
          }
          if (!includeTransientFields && (readMethod != null) && (readMethod.getAnnotation(Transient.class) != null)) {
            return;
          }
          final Method writeMethod = PropertyUtils.getWriteMethod(pd);
          processProperty(pd.getName(), pd.getPropertyType(), readMethod, writeMethod, type, referenceType, properties);
        } catch (final Exception e) {
          throw new RuntimeException("Unexpected error while trying to resolve property " + referenceType.getCanonicalName() + ", [" + pd.getName() + "]", e);
        }
      }
    
    }
    

    然后需要注册 PropertyResolver

    factoryBuilder.propertyResolverStrategy(new LenientIntrospectorPropertyResolver());
    

    【讨论】:

      猜你喜欢
      • 2014-04-01
      • 2021-11-22
      • 2012-08-14
      • 2011-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-07
      • 1970-01-01
      相关资源
      最近更新 更多