Spring 5 不可变形式,当没有参数构造函数时也使用全参数构造函数

Spring 5 immutable form to use an all arg constructor when there is No argument constructor as well

在不可变的 class/object 中,我有一个无参数构造函数将值初始化为 default/null,另一个必需的参数构造函数将所有值初始化为构造函数的参数。

使用表单绑定时(通过在控制器的请求参数中指定),spring 总是调用无参数构造函数而不初始化值。如何确保 spring 仅调用所需的参数构造函数?

这是 spring 版本 5.1.5。我也尝试在 "required argument constructor" 上添加 @ConstructorProperties,但无济于事。


我的不可变 form/bean 对象:

public class ImmutableObj {
    private final Integer id;
    private final String name;

    // no arg constructor
    // spring calls this one when resolving request params
    public ImmutableObj() {
        this(null, null);
    }

    // required args constructor
    // I want spring to call this one when resolving request params
    @ConstructorProperies({"id", "name"})
    public ImmutableObj(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

还有我的控制器:

@Controller
public class MyController {
    @GetMapping("myStuff")
    public String getMyStuff(ImmutableObj requestParams) {
        // here the value of request params
        // has nulls due to no arg constructor being called 
        return "someStuff";
    }
}

调用“/myStuff?id=123&name=hello”时

预计 - requestParams.getId()=123, requestParams.getName()=hello

实际 - requestParams.getId()=null, requestParams.getName()=null


更新!!!!!!!!!!!!!!!

删除无参数构造函数后,我现在 运行 遇到组合问题:

public class ImmutableObj {
    private final SomeOtherObj someOtherObj;

    public ImmutableObj(SomeOtherObj obj) {
        someOtherObj = obj;
    }
}

public class SomeOtherObj {
    private final Integer id;
    private final String name;

    public SomeOtherObj(Integer id, String name) {
        this.id = id;
        this.name = name;
    }
}

并且 spring 抛出:

Could not instantiate property type [SomeOtherObj] to auto-grow nested property path; nested exception is java.lang.NoSuchMethodException: SomeOtherObj.<init>()

Spring is always calling the no argument constructor and not initializing the values.

当Spring看到class有多个构造函数时,它会去寻找一个无参数的。如果Spring没有找到,就会抛出异常。

当Spring看到class只有一个构造函数时,无论它有多少个参数,它都会接受它。

How can I ensure spring to call the required argument constructor only?

唯一的办法是在class中只有一个构造函数。为了使 Spring.

明确

作为旁注,

  1. 如果字段名称对应于 URL 参数名称,则不需要 @ConstructorProperies({"id", "name"})。 Spring 可以解决这个问题。

  2. public ImmutableObj() {
        this(null, null);
    }
    

不是个好主意。 ImmutableObj.empty()会更好。

作为奖励,如果您想了解幕后发生的事情,这里是我所说的片段

if (ctor == null) {
  Constructor<?>[] ctors = clazz.getConstructors();
  if (ctors.length == 1) {
    ctor = ctors[0];
  } else {
    try {
      ctor = clazz.getDeclaredConstructor();
    } catch (NoSuchMethodException var10) {
      throw new IllegalStateException("No primary or default constructor found for " + clazz, var10);
    }
  }
}