Custom converter with Spring dependency injection

纵饮孤独 提交于 2019-12-06 08:08:24

问题


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?


回答1:


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>



回答2:


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>



回答3:


Unfortunately, this is not supported.




回答4:


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.




回答5:


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>



回答6:


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


来源:https://stackoverflow.com/questions/6695884/custom-converter-with-spring-dependency-injection

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!