Allow binding to package private methods

Closes gh-17394
pull/17411/head
Phillip Webb 5 years ago
parent 27cce996fb
commit c94a7dfa04

@ -149,9 +149,9 @@ class JavaBeanBinder implements DataObjectBinder {
private boolean isCandidate(Method method) {
int modifiers = method.getModifiers();
return Modifier.isPublic(modifiers) && !Modifier.isAbstract(modifiers) && !Modifier.isStatic(modifiers)
&& !Object.class.equals(method.getDeclaringClass())
&& !Class.class.equals(method.getDeclaringClass());
return !Modifier.isPrivate(modifiers) && !Modifier.isProtected(modifiers) && !Modifier.isAbstract(modifiers)
&& !Modifier.isStatic(modifiers) && !Object.class.equals(method.getDeclaringClass())
&& !Class.class.equals(method.getDeclaringClass()) && method.getName().indexOf('$') == -1;
}
private void addMethodIfPossible(Method method, String prefix, int parameterCount,

@ -192,8 +192,17 @@ class ValueObjectBinder implements DataObjectBinder {
@SuppressWarnings("unchecked")
static <T> ValueObject<T> get(Class<T> type) {
Constructor<?>[] constructors = type.getDeclaredConstructors();
return (constructors.length != 1) ? null : get((Constructor<T>) constructors[0]);
Constructor<?> constructor = null;
for (Constructor<?> candidate : type.getDeclaredConstructors()) {
int modifiers = candidate.getModifiers();
if (!Modifier.isPrivate(modifiers) && !Modifier.isProtected(modifiers)) {
if (constructor != null) {
return null;
}
constructor = candidate;
}
}
return get((Constructor<T>) constructor);
}
static <T> DefaultValueObject<T> get(Constructor<T> constructor) {

@ -529,6 +529,15 @@ class JavaBeanBinderTests {
assertThat(result.getNested().getBar()).isEqualTo(456);
}
@Test
void bindWhenHasPackagePrivateSetterShouldBind() {
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
source.put("foo.property", "test");
this.sources.add(source);
PackagePrivateSetterBean bean = this.binder.bind("foo", Bindable.of(PackagePrivateSetterBean.class)).get();
assertThat(bean.getProperty()).isEqualTo("test");
}
public static class ExampleValueBean {
private int intValue;
@ -1011,4 +1020,18 @@ class JavaBeanBinderTests {
}
public static class PackagePrivateSetterBean {
private String property;
public String getProperty() {
return this.property;
}
void setProperty(String property) {
this.property = property;
}
}
}

@ -166,6 +166,16 @@ class ValueObjectBinderTests {
assertThat(bean.getDate().toString()).isEqualTo("2019-05-10");
}
@Test
void bindToClassWhenHasPackagePrivateConstructorShouldBind() {
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
source.put("foo.property", "test");
this.sources.add(source);
ExamplePackagePrivateConstructorBean bound = this.binder
.bind("foo", Bindable.of(ExamplePackagePrivateConstructorBean.class)).get();
assertThat(bound.getProperty()).isEqualTo("test");
}
@Test
void createShouldReturnCreatedValue() {
ExampleValueBean value = this.binder.bindOrCreate("foo", Bindable.of(ExampleValueBean.class));
@ -370,4 +380,18 @@ class ValueObjectBinderTests {
}
public static class ExamplePackagePrivateConstructorBean {
private final String property;
ExamplePackagePrivateConstructorBean(String property) {
this.property = property;
}
public String getProperty() {
return this.property;
}
}
}

Loading…
Cancel
Save