使用 Spring 依赖注入的自定义转换器

发布于 2024-11-24 01:22:05 字数 458 浏览 3 评论 0原文

有没有一种方法可以在 Dozer 中定义自定义转换器,用于将一种顶级类型转换为另一种顶级类型,而另一种类型本身就是一个 Spring bean,因此可以注入其依赖项?

dozer 文档建议添加以下 XML 定义:

  <converter type="org.dozer.converters.TestCustomConverter" >
    <class-a>org.dozer.vo.CustomDoubleObject</class-a>
    <class-b>java.lang.Double</class-b>
  </converter>

不幸的是,这会导致 Dozer 直接实例化 org.dozer.converters.TestCustomConverter,这将跳过依赖注入。有没有办法引用 Spring bean?

Is there a way to define a custom converter in Dozer for converting one top-level type to another, which is itself a Spring bean and thus can get its dependencies injected?

The dozer docs propose to add the following XML definition:

  <converter type="org.dozer.converters.TestCustomConverter" >
    <class-a>org.dozer.vo.CustomDoubleObject</class-a>
    <class-b>java.lang.Double</class-b>
  </converter>

Unfortunately, this causes Dozer to instantiate org.dozer.converters.TestCustomConverter directly, which will skip dependency injection. Is there a way to reference a Spring bean instead?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

浅暮の光 2024-12-01 01:22:05

在前面的答案中的 CustomConverterWithIds 旁边,还可以注入自定义转换器来覆盖映射文件的配置部分中定义的转换器。这样,推土机将使用注入的转换器,而不是使用默认构造函数实例化转换器。

<bean id="dozerMapper" class="org.dozer.DozerBeanMapper" scope="singleton">
    <property name="mappingFiles">
        <list>
            <value><mapping-file-name1></value>
            <value><mapping-file-name2></value>
        </list> 
    </property>
    <property name="customConverters">
        <list>
            <ref bean="entityConverter"/>
        </list>
    </property>
</bean>

<configuration>
   <custom-converters>
     <converter type="my.domain.EntityConverter">
        <class-a>java.lang.Integer</class-a>
        <class-b>my.domain.MyEntity</class-b>
     </converter>
   <custom-converters>
</configuration>

<beans   .... >
   <bean id="entityConverter" class="my.domain.EntityConverter">
        <property ....
   </bean
</beans>

Next to CustomConverterWithIds as in previous answer it is also possible to inject custom converters to override the converters defined in the configuration part in the mapping file. That way dozer will use the injected converter instead of instantiating one using the default constructor.

<bean id="dozerMapper" class="org.dozer.DozerBeanMapper" scope="singleton">
    <property name="mappingFiles">
        <list>
            <value><mapping-file-name1></value>
            <value><mapping-file-name2></value>
        </list> 
    </property>
    <property name="customConverters">
        <list>
            <ref bean="entityConverter"/>
        </list>
    </property>
</bean>

<configuration>
   <custom-converters>
     <converter type="my.domain.EntityConverter">
        <class-a>java.lang.Integer</class-a>
        <class-b>my.domain.MyEntity</class-b>
     </converter>
   <custom-converters>
</configuration>

<beans   .... >
   <bean id="entityConverter" class="my.domain.EntityConverter">
        <property ....
   </bean
</beans>
↙厌世 2024-12-01 01:22:05

如果您的自定义转换器是 spring bean,则 Dozer bean 映射器的属性“customConvertersWithIds”可用于引用转换器 spring bean。然后使用此 id 来引用映射中的自定义转换器。以下是我让它为我工作的方法:

<bean id="dozerMapper" class="org.dozer.DozerBeanMapper" scope="singleton">
        <property name="mappingFiles">
            <list>
                <value><mapping-file-name1></value>
                <value><mapping-file-name2></value>
            </list>
        </property>
        <property name="customConvertersWithId">
            <map>
                <entry key="crbConverter" value-ref="loadableFooBeanConverter"/>
                <entry key="sbConverter" value-ref="loadableXyzBeanConverter"/>
            </map>
        </property>
    </bean>

我对转换器类进行了注释,例如 @component("loadableFooBeanConverter")

映射的示例:

<mapping>
        <class-a>${Abc}</class-a>
        <class-b>${AbcBean}</class-b>
           <field custom-converter-id="sbConverter">
            <a>XyzId</a>
            <b>Xyz</b>
            <b-hint>${XyzBean}</b-hint>
        </field>
</mapping>

If your custom converter is a spring bean then the property 'customConvertersWithIds' of Dozer bean mapper can be used to refer to the converter spring bean. Then use this id to refer to the custom converter in the mappings. Here is how I made it work for me:

<bean id="dozerMapper" class="org.dozer.DozerBeanMapper" scope="singleton">
        <property name="mappingFiles">
            <list>
                <value><mapping-file-name1></value>
                <value><mapping-file-name2></value>
            </list>
        </property>
        <property name="customConvertersWithId">
            <map>
                <entry key="crbConverter" value-ref="loadableFooBeanConverter"/>
                <entry key="sbConverter" value-ref="loadableXyzBeanConverter"/>
            </map>
        </property>
    </bean>

I have the converter classes annotated, e.g., @component("loadableFooBeanConverter")

An example of a mapping:

<mapping>
        <class-a>${Abc}</class-a>
        <class-b>${AbcBean}</class-b>
           <field custom-converter-id="sbConverter">
            <a>XyzId</a>
            <b>Xyz</b>
            <b-hint>${XyzBean}</b-hint>
        </field>
</mapping>
掩于岁月 2024-12-01 01:22:05

Spring Boot for Gunjan 的答案中的 Java 配置可以如下所示:

将自定义转换器创建为 bean,如下所示:

@Component
public class LoadableFooBeanConverter extends DozerConverter<BarBean, FooBean> {
    private final Util util; // Any beans that need to be injected into the custom converter

    @Autowired // Constructor Injection
    public LoadableFooBeanConverter(Util util) {
        super(BarBean.class, FooBean.class);
        this.util = util;
    }

    @Override
    public FooBean convertTo(final BarBean source, final FooBean destination) {
        // Your logic
    }

    @Override
    public BarBean convertFrom(final FooBean source, final BarBean destination) {
        // Your logic
    }
}

创建 Mapper 组件并注册自定义转换器,如下所示:

@Component
@RequiredArgsConstructor // lombok annotation
public class DozerMapper {
    @Autowired
    private final LoadableFooBeanConverter loadableFooBeanConverter;

    @Getter // lombok annotation
    private Mapper mapper;

    @PostConstruct
    public void init() {
        this.mapper = DozerBeanMapperBuilder.create()
                .withMappingBuilders(BarMappingBuilder.builder().build())
                .withCustomConverterWithId("loadableFooBeanConverter", loadableFooBeanConverter)
                .build();
    }

    @Builder // lombok annocation
    private static class BarMappingBuilder extends BeanMappingBuilder {
        @Override
        protected void configure() {
            mapping(FooBar.class, FooBarFoo.class)
                    .fields("fooBean", "barBean", FieldsMappingOptions.customConverterId("loadableFooBeanConverter"));
        }
    }
}

The Java configuration in Spring Boot for Gunjan's answer can be as following:

Create the custom converter as a bean as below:

@Component
public class LoadableFooBeanConverter extends DozerConverter<BarBean, FooBean> {
    private final Util util; // Any beans that need to be injected into the custom converter

    @Autowired // Constructor Injection
    public LoadableFooBeanConverter(Util util) {
        super(BarBean.class, FooBean.class);
        this.util = util;
    }

    @Override
    public FooBean convertTo(final BarBean source, final FooBean destination) {
        // Your logic
    }

    @Override
    public BarBean convertFrom(final FooBean source, final BarBean destination) {
        // Your logic
    }
}

Create the Mapper component and register the custom converter as below:

@Component
@RequiredArgsConstructor // lombok annotation
public class DozerMapper {
    @Autowired
    private final LoadableFooBeanConverter loadableFooBeanConverter;

    @Getter // lombok annotation
    private Mapper mapper;

    @PostConstruct
    public void init() {
        this.mapper = DozerBeanMapperBuilder.create()
                .withMappingBuilders(BarMappingBuilder.builder().build())
                .withCustomConverterWithId("loadableFooBeanConverter", loadableFooBeanConverter)
                .build();
    }

    @Builder // lombok annocation
    private static class BarMappingBuilder extends BeanMappingBuilder {
        @Override
        protected void configure() {
            mapping(FooBar.class, FooBarFoo.class)
                    .fields("fooBean", "barBean", FieldsMappingOptions.customConverterId("loadableFooBeanConverter"));
        }
    }
}
﹏雨一样淡蓝的深情 2024-12-01 01:22:05

不幸的是,这不受支持。

Unfortunately, this is not supported.

画▽骨i 2024-12-01 01:22:05

为了将 Spring bean 作为自定义转换器注入,我修补了原始的 Dozer。您可以查看我的更改并在您可以接受的情况下使用它们。更新后的源位于 https://bitbucket.org/JRS/open-dozer

您仍然需要将自定义转换器记录添加到全局配置中。

To inject Spring bean as a custom converter I patched the original Dozer. You can review my changes and use them if they are acceptable for you. The updated sources are located on https://bitbucket.org/JRS/open-dozer.

You still need add custom converter record to the global configuration.

表情可笑 2024-12-01 01:22:05

为了改进@Chris的答案,您可以直接引用类以避免声明bean。

在 dozer bean 声明中声明您的自定义转换器 bean。

<bean id="DozerMapper" class="org.dozer.DozerBeanMapper">
    <property name="mappingFiles">
        <list>
            <value>mapping.xml</value>
        </list>
    </property>
    <property name="customConverters">
        <list>
            <bean class="com.pharmagest.monalisa.rest.service.mapper.MyConverter"/>
        </list>
    </property>
</bean>

在配置中声明您的映射后(对我来说,在mapping.xml 文件中)。

<configuration>
        <stop-on-errors>true</stop-on-errors>
        <date-format>MM/dd/yyyy HH:mm</date-format>
        <wildcard>true</wildcard>
        <custom-converters>
            <converter type="com.pharmagest.monalisa.rest.service.mapper.MyConverter">
                <class-a>com.project.ClassA</class-a>
                <class-b>com.project.ClassB</class-b>
            </converter>
        </custom-converters>
</configuration>

To improve @Chris answer, you can refer class directly to avoid to declare a bean.

Declare your custom converter bean in the dozer bean declaration.

<bean id="DozerMapper" class="org.dozer.DozerBeanMapper">
    <property name="mappingFiles">
        <list>
            <value>mapping.xml</value>
        </list>
    </property>
    <property name="customConverters">
        <list>
            <bean class="com.pharmagest.monalisa.rest.service.mapper.MyConverter"/>
        </list>
    </property>
</bean>

After declare your mapping in the configuration (for me, in the mapping.xml file).

<configuration>
        <stop-on-errors>true</stop-on-errors>
        <date-format>MM/dd/yyyy HH:mm</date-format>
        <wildcard>true</wildcard>
        <custom-converters>
            <converter type="com.pharmagest.monalisa.rest.service.mapper.MyConverter">
                <class-a>com.project.ClassA</class-a>
                <class-b>com.project.ClassB</class-b>
            </converter>
        </custom-converters>
</configuration>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文