Spring的5.3.18版本及以上BeanUtils踩坑和避坑经历

669 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

1. 从spring的那个安全漏洞说起

4月份时候spring官方公布了漏洞- [CVE-2022-22965] 参考地址: tanzu.vmware.com/security/cv…
对应的安全版本:

  • springframework == 5.3.18 那么通过升级maven依赖的方式来更新spring版本
<properties>
	<spring-framework.version>5.3.18</spring-framework.version>
</properties>

原来我使用的spring-framework版本是5.1.19,自然必须要升级从而处理掉安全漏洞,然后在升级后一个潜藏的问题发生了

2.BeanUtils.copyProperties 针对包含内部类集合属性的赋值问题

该工具类在springframework-beans 5.3.x版本以后Java对象里包含内部类集合属性的copy无法复制最内层的内部类属性。但之前低版本的springframework-beans 5.1.x没有这个问题,能够赋值成功。代码示例:

  • 源copy类
public class BodySourceDTO {
private List<BodyCoordinate> bodyCoordinates;

public List<BodyCoordinate> getBodyCoordinates() {
    return bodyCoordinates;
}

public void setBodyCoordinates(List<BodyCoordinate> bodyCoordinates) {
    this.bodyCoordinates = bodyCoordinates;
}

public static class BodyCoordinate{
    private float height;
    private float width;
    private float x;
    private float y;

    public float getHeight() {
        return height;
    }

    public void setHeight(float height) {
        this.height = height;
    }
}
}
  • 目标DTO类:
public class BodyResultDTO {
private List<BodySourceDTO.BodyCoordinate> bodyCoordinates;

public List<BodySourceDTO.BodyCoordinate> getBodyCoordinates() {
    return bodyCoordinates;
}

public void setBodyCoordinates(List<BodySourceDTO.BodyCoordinate> bodyCoordinates) {
    this.bodyCoordinates = bodyCoordinates;
}

public static class BodyCoordinate{
    private float height;
    private float width;
    private float x;
    private float y;

    public float getHeight() {
        return height;
    }

    public void setHeight(float height) {
        this.height = height;
    }

    public float getWidth() {
        return width;
    }

    public void setWidth(float width) {
        this.width = width;
    }

    public float getX() {
        return x;
    }

    public void setX(float x) {
        this.x = x;
    }

    public float getY() {
        return y;
    }

    public void setY(float y) {
        this.y = y;
    }
}
}
  • 类copy的代码示例:
public class Test {
    public static void main(String[] args) {
        BodyResultDTO bodyResultDTO = new BodyResultDTO();
        BodySourceDTO sourceDTO = new BodySourceDTO();

        ArrayList<BodySourceDTO.BodyCoordinate> bodyCoordinates = new ArrayList<>();

        BodySourceDTO.BodyCoordinate bodyCoordinate = new BodySourceDTO.BodyCoordinate();
        bodyCoordinate.setX(0.966667f);
        bodyCoordinate.setY(0.966667f);
        bodyCoordinate.setHeight(0.966667f);
        bodyCoordinate.setWidth(0.966667f);
        bodyCoordinates.add(bodyCoordinate);
        sourceDTO.setBodyCoordinates(bodyCoordinates);

        //重点来了
        BeanUtils.copyProperties(sourceDTO, bodyResultDTO);
    }
}
  • 输出结果

Snipaste_2022-06-11_16-25-25.png

原因分析

通过追踪调试源代码发现,高版本的spring的BeanUtils工具类复制内部集合属性时,加强了类型限制,无法实现集合属性的深复制。 因此最终只能手动处理这种包含有内部类属性的对象复制