Draymonders / Code-Life

The marathon continues though.
27 stars 3 forks source link

mongoRepository 被final修饰的字段 setProperty 失败 #85

Open Draymonders opened 3 years ago

Draymonders commented 3 years ago

setProperty 抛出异常 IllegalStateException

报错的源码如下

if (!property.isImmutable() || property.getWither() != null || ReflectionUtils.isKotlinClass(owner.getType())) {

    delegate.setProperty(property, value);
    this.bean = delegate.getBean();

    return;
}

PreferredConstructor<?, ?> constructor = owner.getPersistenceConstructor();

if (constructor == null) {
    throw new IllegalStateException(String.format(NO_SETTER_OR_CONSTRUCTOR, property.getName(), owner.getType()));
}

if (!constructor.isConstructorParameter(property)) {
    throw new IllegalStateException(
            String.format(NO_CONSTRUCTOR_PARAMETER, property.getName(), constructor.getConstructor()));
}

constructor.getParameters().forEach(it -> {

    if (it.getName() == null) {
        throw new IllegalStateException(
                String.format("Cannot detect parameter names of copy constructor of %s!", owner.getType()));
    }
});

EntityInstantiator instantiator = instantiators.getInstantiatorFor(owner);

this.bean = (T) instantiator.createInstance(owner, new ParameterValueProvider() {

    /*
        * (non-Javadoc)
        * @see org.springframework.data.mapping.model.ParameterValueProvider#getParameterValue(org.springframework.data.mapping.PreferredConstructor.Parameter)
        */
    @Override
    @Nullable
    @SuppressWarnings("null")
    public Object getParameterValue(Parameter parameter) {

        return property.getName().equals(parameter.getName()) //
                ? value
                : delegate.getProperty(owner.getRequiredPersistentProperty(parameter.getName()));
    }
});

阅读代码, mongoRepositorysetPorperty 的时候 会先判断 当前字段是否是不可变的,是否被@wither修饰,以及是否是kotlin的源码,如果字段不是final修饰的,或者变量有@wither修饰,则可以直接设置value。

接下来,判断字段是否是构造函数中出现的,如果也不是,说明 字段既是final修饰,又没有构造函数可以初始化, 就会报错。

最后解决方案: