Java 反思:为集合类型对象调用 Setter 和 Getter 方法
Java Reflection: Invoking Setter and Getter method for collection type Object
我有两个不同的用户定义对象包.....
1) ws.lender.dto (all Objects exists in this package are source side).
2) copl.com.dto (all Objects exists in this package are destination side).
两侧的对象层次结构和对象名称不同。我想
按字段将源端对象复制到目标端对象字段或
通过 getter 和 setter 使用反射。
例如
源端对象
package ws.lender.dto;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "CustomerAddresses", propOrder = {
"previousAddresses"
})
public class CustomerAddresses {
protected PreviousAddresses previousAddresses;
public PreviousAddresses getPreviousAddresses() {
return previousAddresses;
}
public void setPreviousAddresses(PreviousAddresses value) {
this.previousAddresses = value;
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PreviousAddresses", propOrder = {
"previousAddress"
})
public class PreviousAddresses {
@XmlElement(name = "PreviousAddress", required = true)
protected List<PreviousAddress> previousAddress;
public List<PreviousAddress> getPreviousAddress() {
if (previousAddress == null) {
previousAddress = new ArrayList<PreviousAddress>();
}
return this.previousAddress;
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PreviousAddress", propOrder = {
"streetNo",
"streetName"
})
public class PreviousAddress {
@XmlElement(name = "StreetNo", required = true)
protected String streetNo;
@XmlElement(name = "StreetName", required = true)
protected String streetName;
public String getStreetNo() {
return streetNo;
}
public void setStreetNo(String value) {
this.streetNo = value;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String value) {
this.streetName = value;
}
}
目标方对象
package copl.com.dto;
@javax.persistence.Entity
public class Customer implements java.io.Serializable
{
private Set<CustomerAddress> customerAddresses;
public Set<CustomerAddress> getCustomerAddresses()
{
return customerAddresses;
}
public void setCustomerAddresses(Set<CustomerAddress> customerAddresses)
{
this.customerAddresses = customerAddresses;
}
}
@javax.persistence.Entity
public class CustomerAddress implements java.io.Serializable
{
private String unitNumber;
private String streetName;
private String streetNumber;
public String getUnitNumber()
{
return unitNumber;
}
public void setUnitNumber(String unitNumber)
{
this.unitNumber = unitNumber;
}
public String getStreetName()
{
return streetName;
}
public String getStreetNumber()
{
return streetNumber;
}
public void setStreetName(String streetName)
{
this.streetName = streetName;
}
public void setStreetNumber(String streetNumber)
{
this.streetNumber = streetNumber;
}
}
如果我没理解错的话,您需要一种方法将所有同名属性从一个对象复制到另一个对象。类似命名的属性是这样的情况,其中源对象有一个名为 getPropertyName() 的方法,而目标对象有一个名为 setPropertyName() 的方法。
如果这是正确的,那么您想使用 Apache Commons 库中 BeanUtils class 的 copyProperties 方法。文档是 here.
现在,在您的示例中,您有一些名称不同的相应属性,例如 StreetNumber 和 StreetNo。恐怕没有简单的方法可以通过反射自动处理这类事情;您需要自己定义源属性和目标属性之间的映射,也许可以通过定义帮助程序 class 来进行复制。
我认为您可以使用 MapStruct 在具有不同属性名称的 POJO 之间进行映射。
但是你的场景很复杂,因为你要将ws.lender.dto.CustomerAddresses
转换为copl.com.dto.Customer
,这意味着将包含的List<ws.lender.dto.PreviousAddress>
转换为ws.lender.dto.PreviousAddresses
对象,以Set<copl.com.dto.CustomerAddress>
包含在 copl.com.dto.Customer
对象中。
所以,我会一步一步解释。
1。从 ws.lender.dto.PreviousAddress
转换为 copl.com.dto.CustomerAddress
要进行此转换,您需要一个接口(MapStruct 将为此创建一个实例)负责从源对象映射到目标对象:
import ws.lender.dto.PreviousAddress;
import copl.com.dto.CustomerAddress;
@Mapper
public interface CustomerAddressesMapper{
CustomerAddressesMapper INSTANCE = Mappers.getMapper( CustomerAddressesMapper.class );
@Mappings(@Mapping(source = "streetNo", target = "streetNumber")
CustomerAddress previousToCustomerObject(PreviousAddress address);
}
考虑到 streetNo
属性必须映射到 streetNumber
,此接口会将 PreviousAddress
对象映射到 CustomerAddress
。 unitNumber
属性没有映射,因为没有它的来源。
2。将 List<ws.lender.dto.PreviousAddress>
转换为 Set<copl.com.dto.CustomerAddress>
现在您必须向现有 CustomerAddressesMapper
接口添加另一种映射方法:
Set<CustomerAddress> previousToCustomerSet(List<PreviousAddress> addresses);
此方法将使用前者 previousToCustomerObject
将源列表的每个元素转换为目标集。
3。从 ws.lender.dto.CustomerAddresses
转换为 copl.com.dto.Customer
最后需要将最后一个映射方法添加到CustomerAddressesMapper
接口:
@Mappings(@Mapping(source = "previousAddresses.previousAddress", target = "customerAddresses")
Customer customerAddrsToCustomerObject(CustomerAddresses addresses);
这是您映射原始对象的地方,使用以前的方法将 previousAddresses.previousAddress
属性转换为 customerAddresses
属性。
4。使用映射器
要使用映射器,您必须编写如下代码:
CustomerAddressesMapper mapper = CustomerAddressesMapper.INSTANCE;
CustomerAddresses origin = //Retrieve it from anywhere
Customer dest = mapper.customerAddrsToCustomerObject(origin);
5。设置
MapStruct 是一个源代码生成器,因此您需要正确配置 pom.xml
以包含 MapStruct 依赖项并调用此代码生成。你可以看看如何做到这一点 here
好吧,我不会构建 运行 这段代码,但这是实现它的方法。
希望对您有所帮助!
您可以尝试 Object Mapper 更好地进行投射或复制。其他包中其他 classes 的对象,您可以添加一些 属性 值,例如
senderClass and rvcClass
稍后您可以阅读这些属性并继续转换 class。可能您已经准备好发送方 class 与接收方 class 的映射。
我研究了很多用于此作业的对象映射框架,例如
最后我选择了Orika框架来完成上面的对象到对象的映射。我们可以通过其他映射器框架进行映射,但我喜欢 Orika 框架,因为这个框架非常容易用于将对象映射到对象。
我会一步步解释的
1.创建源端对象和目标端对象的对象。
像这样..
Customer destination = new Customer();
CustomerAddresses source = new CustomerAddresses();
source = filledCustomerAddressesObject();
2。构建 DefaultMapperFactory
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
3。映射字段
ClassMapBuilder<CustomerAddresses, Customer> builder;
builder= mapperFactory.classMap(CustomerAddresses.class, Customer.class).constructorA();
builder.field("previousAddresses.previousAddress{streetNo}","customerAddresses{streetNumber}");
builder.field("previousAddresses.previousAddress{streetName}","customerAddresses{streetName}");
builder.register();
BoundMapperFacade<CustomerAddresses, Customer> boundMapper;
boundMapper = mapperFactory.getMapperFacade(CustomerAddresses.class, Customer.class);
destination = boundMapper.map(source, destination);
干得漂亮干杯
我有两个不同的用户定义对象包.....
1) ws.lender.dto (all Objects exists in this package are source side).
2) copl.com.dto (all Objects exists in this package are destination side).
两侧的对象层次结构和对象名称不同。我想 按字段将源端对象复制到目标端对象字段或 通过 getter 和 setter 使用反射。
例如
源端对象
package ws.lender.dto;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "CustomerAddresses", propOrder = {
"previousAddresses"
})
public class CustomerAddresses {
protected PreviousAddresses previousAddresses;
public PreviousAddresses getPreviousAddresses() {
return previousAddresses;
}
public void setPreviousAddresses(PreviousAddresses value) {
this.previousAddresses = value;
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PreviousAddresses", propOrder = {
"previousAddress"
})
public class PreviousAddresses {
@XmlElement(name = "PreviousAddress", required = true)
protected List<PreviousAddress> previousAddress;
public List<PreviousAddress> getPreviousAddress() {
if (previousAddress == null) {
previousAddress = new ArrayList<PreviousAddress>();
}
return this.previousAddress;
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PreviousAddress", propOrder = {
"streetNo",
"streetName"
})
public class PreviousAddress {
@XmlElement(name = "StreetNo", required = true)
protected String streetNo;
@XmlElement(name = "StreetName", required = true)
protected String streetName;
public String getStreetNo() {
return streetNo;
}
public void setStreetNo(String value) {
this.streetNo = value;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String value) {
this.streetName = value;
}
}
目标方对象
package copl.com.dto;
@javax.persistence.Entity
public class Customer implements java.io.Serializable
{
private Set<CustomerAddress> customerAddresses;
public Set<CustomerAddress> getCustomerAddresses()
{
return customerAddresses;
}
public void setCustomerAddresses(Set<CustomerAddress> customerAddresses)
{
this.customerAddresses = customerAddresses;
}
}
@javax.persistence.Entity
public class CustomerAddress implements java.io.Serializable
{
private String unitNumber;
private String streetName;
private String streetNumber;
public String getUnitNumber()
{
return unitNumber;
}
public void setUnitNumber(String unitNumber)
{
this.unitNumber = unitNumber;
}
public String getStreetName()
{
return streetName;
}
public String getStreetNumber()
{
return streetNumber;
}
public void setStreetName(String streetName)
{
this.streetName = streetName;
}
public void setStreetNumber(String streetNumber)
{
this.streetNumber = streetNumber;
}
}
如果我没理解错的话,您需要一种方法将所有同名属性从一个对象复制到另一个对象。类似命名的属性是这样的情况,其中源对象有一个名为 getPropertyName() 的方法,而目标对象有一个名为 setPropertyName() 的方法。
如果这是正确的,那么您想使用 Apache Commons 库中 BeanUtils class 的 copyProperties 方法。文档是 here.
现在,在您的示例中,您有一些名称不同的相应属性,例如 StreetNumber 和 StreetNo。恐怕没有简单的方法可以通过反射自动处理这类事情;您需要自己定义源属性和目标属性之间的映射,也许可以通过定义帮助程序 class 来进行复制。
我认为您可以使用 MapStruct 在具有不同属性名称的 POJO 之间进行映射。
但是你的场景很复杂,因为你要将ws.lender.dto.CustomerAddresses
转换为copl.com.dto.Customer
,这意味着将包含的List<ws.lender.dto.PreviousAddress>
转换为ws.lender.dto.PreviousAddresses
对象,以Set<copl.com.dto.CustomerAddress>
包含在 copl.com.dto.Customer
对象中。
所以,我会一步一步解释。
1。从 ws.lender.dto.PreviousAddress
转换为 copl.com.dto.CustomerAddress
要进行此转换,您需要一个接口(MapStruct 将为此创建一个实例)负责从源对象映射到目标对象:
import ws.lender.dto.PreviousAddress;
import copl.com.dto.CustomerAddress;
@Mapper
public interface CustomerAddressesMapper{
CustomerAddressesMapper INSTANCE = Mappers.getMapper( CustomerAddressesMapper.class );
@Mappings(@Mapping(source = "streetNo", target = "streetNumber")
CustomerAddress previousToCustomerObject(PreviousAddress address);
}
考虑到 streetNo
属性必须映射到 streetNumber
,此接口会将 PreviousAddress
对象映射到 CustomerAddress
。 unitNumber
属性没有映射,因为没有它的来源。
2。将 List<ws.lender.dto.PreviousAddress>
转换为 Set<copl.com.dto.CustomerAddress>
现在您必须向现有 CustomerAddressesMapper
接口添加另一种映射方法:
Set<CustomerAddress> previousToCustomerSet(List<PreviousAddress> addresses);
此方法将使用前者 previousToCustomerObject
将源列表的每个元素转换为目标集。
3。从 ws.lender.dto.CustomerAddresses
转换为 copl.com.dto.Customer
最后需要将最后一个映射方法添加到CustomerAddressesMapper
接口:
@Mappings(@Mapping(source = "previousAddresses.previousAddress", target = "customerAddresses")
Customer customerAddrsToCustomerObject(CustomerAddresses addresses);
这是您映射原始对象的地方,使用以前的方法将 previousAddresses.previousAddress
属性转换为 customerAddresses
属性。
4。使用映射器
要使用映射器,您必须编写如下代码:
CustomerAddressesMapper mapper = CustomerAddressesMapper.INSTANCE;
CustomerAddresses origin = //Retrieve it from anywhere
Customer dest = mapper.customerAddrsToCustomerObject(origin);
5。设置
MapStruct 是一个源代码生成器,因此您需要正确配置 pom.xml
以包含 MapStruct 依赖项并调用此代码生成。你可以看看如何做到这一点 here
好吧,我不会构建 运行 这段代码,但这是实现它的方法。
希望对您有所帮助!
您可以尝试 Object Mapper 更好地进行投射或复制。其他包中其他 classes 的对象,您可以添加一些 属性 值,例如
senderClass and rvcClass
稍后您可以阅读这些属性并继续转换 class。可能您已经准备好发送方 class 与接收方 class 的映射。
我研究了很多用于此作业的对象映射框架,例如
最后我选择了Orika框架来完成上面的对象到对象的映射。我们可以通过其他映射器框架进行映射,但我喜欢 Orika 框架,因为这个框架非常容易用于将对象映射到对象。
我会一步步解释的
1.创建源端对象和目标端对象的对象。
像这样..
Customer destination = new Customer(); CustomerAddresses source = new CustomerAddresses(); source = filledCustomerAddressesObject();
2。构建 DefaultMapperFactory
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
3。映射字段
ClassMapBuilder<CustomerAddresses, Customer> builder;
builder= mapperFactory.classMap(CustomerAddresses.class, Customer.class).constructorA();
builder.field("previousAddresses.previousAddress{streetNo}","customerAddresses{streetNumber}");
builder.field("previousAddresses.previousAddress{streetName}","customerAddresses{streetName}");
builder.register();
BoundMapperFacade<CustomerAddresses, Customer> boundMapper;
boundMapper = mapperFactory.getMapperFacade(CustomerAddresses.class, Customer.class);
destination = boundMapper.map(source, destination);
干得漂亮干杯