Ignore static and abstract accessors
This commit updates the annotation processor and the binder to ignore any static or abstract method that has the characteristics of a JavaBean accessor. As a result, no property is generated for those (invalid) accessor and no binding occurs on them either. Closes gh-12390
This commit is contained in:
parent
72afdc676d
commit
7d1faa1c88
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2017 the original author or authors.
|
* Copyright 2012-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -21,6 +21,7 @@ import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.annotation.processing.ProcessingEnvironment;
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
|
@ -97,7 +98,7 @@ class TypeElementMembers {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processMethod(ExecutableElement method) {
|
private void processMethod(ExecutableElement method) {
|
||||||
if (method.getModifiers().contains(Modifier.PUBLIC)) {
|
if (isPublic(method)) {
|
||||||
String name = method.getSimpleName().toString();
|
String name = method.getSimpleName().toString();
|
||||||
if (isGetter(method) && !this.publicGetters.containsKey(name)) {
|
if (isGetter(method) && !this.publicGetters.containsKey(name)) {
|
||||||
this.publicGetters.put(getAccessorName(name), method);
|
this.publicGetters.put(getAccessorName(name), method);
|
||||||
|
@ -118,6 +119,13 @@ class TypeElementMembers {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isPublic(ExecutableElement method) {
|
||||||
|
Set<Modifier> modifiers = method.getModifiers();
|
||||||
|
return modifiers.contains(Modifier.PUBLIC)
|
||||||
|
&& !modifiers.contains(Modifier.ABSTRACT)
|
||||||
|
&& !modifiers.contains(Modifier.STATIC);
|
||||||
|
}
|
||||||
|
|
||||||
private ExecutableElement getMatchingSetter(List<ExecutableElement> candidates,
|
private ExecutableElement getMatchingSetter(List<ExecutableElement> candidates,
|
||||||
TypeMirror type) {
|
TypeMirror type) {
|
||||||
for (ExecutableElement candidate : candidates) {
|
for (ExecutableElement candidate : candidates) {
|
||||||
|
|
|
@ -81,6 +81,7 @@ import org.springframework.boot.configurationsample.specific.InnerClassRootConfi
|
||||||
import org.springframework.boot.configurationsample.specific.InvalidAccessorProperties;
|
import org.springframework.boot.configurationsample.specific.InvalidAccessorProperties;
|
||||||
import org.springframework.boot.configurationsample.specific.InvalidDoubleRegistrationProperties;
|
import org.springframework.boot.configurationsample.specific.InvalidDoubleRegistrationProperties;
|
||||||
import org.springframework.boot.configurationsample.specific.SimplePojo;
|
import org.springframework.boot.configurationsample.specific.SimplePojo;
|
||||||
|
import org.springframework.boot.configurationsample.specific.StaticAccessor;
|
||||||
import org.springframework.boot.configurationsample.specific.WildcardConfig;
|
import org.springframework.boot.configurationsample.specific.WildcardConfig;
|
||||||
import org.springframework.boot.testsupport.compiler.TestCompiler;
|
import org.springframework.boot.testsupport.compiler.TestCompiler;
|
||||||
import org.springframework.util.FileCopyUtils;
|
import org.springframework.util.FileCopyUtils;
|
||||||
|
@ -365,6 +366,18 @@ public class ConfigurationMetadataAnnotationProcessorTests {
|
||||||
.fromSource(AnnotatedGetter.class));
|
.fromSource(AnnotatedGetter.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void staticAccessor() {
|
||||||
|
ConfigurationMetadata metadata = compile(StaticAccessor.class);
|
||||||
|
assertThat(metadata)
|
||||||
|
.has(Metadata.withGroup("specific").fromSource(StaticAccessor.class));
|
||||||
|
assertThat(metadata).has(Metadata.withProperty("specific.counter",
|
||||||
|
Integer.class).fromSource(StaticAccessor.class).withDefaultValue(42));
|
||||||
|
assertThat(metadata).doesNotHave(Metadata.withProperty("specific.name",
|
||||||
|
String.class).fromSource(StaticAccessor.class));
|
||||||
|
assertThat(metadata.getItems()).hasSize(2);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void innerClassRootConfig() {
|
public void innerClassRootConfig() {
|
||||||
ConfigurationMetadata metadata = compile(InnerClassRootConfig.class);
|
ConfigurationMetadata metadata = compile(InnerClassRootConfig.class);
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2018 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.configurationsample.specific;
|
||||||
|
|
||||||
|
import org.springframework.boot.configurationsample.ConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A property that is exposed by static accessors.
|
||||||
|
*
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
*/
|
||||||
|
@ConfigurationProperties("specific")
|
||||||
|
public class StaticAccessor {
|
||||||
|
|
||||||
|
private static String name;
|
||||||
|
|
||||||
|
private int counter = 42;
|
||||||
|
|
||||||
|
public static String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setName(String name) {
|
||||||
|
StaticAccessor.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCounter() {
|
||||||
|
return this.counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCounter(int counter) {
|
||||||
|
this.counter = counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -118,7 +118,9 @@ class JavaBeanBinder implements BeanBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isCandidate(Method method) {
|
private boolean isCandidate(Method method) {
|
||||||
return Modifier.isPublic(method.getModifiers())
|
int modifiers = method.getModifiers();
|
||||||
|
return Modifier.isPublic(modifiers) && !Modifier.isAbstract(modifiers)
|
||||||
|
&& !Modifier.isStatic(modifiers)
|
||||||
&& !Object.class.equals(method.getDeclaringClass())
|
&& !Object.class.equals(method.getDeclaringClass())
|
||||||
&& !Class.class.equals(method.getDeclaringClass());
|
&& !Class.class.equals(method.getDeclaringClass());
|
||||||
}
|
}
|
||||||
|
|
|
@ -486,6 +486,18 @@ public class JavaBeanBinderTests {
|
||||||
assertThat(bean.getName()).isEqualTo("something");
|
assertThat(bean.getName()).isEqualTo("something");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void bindToClassShouldIgnoreStaticAccessors() {
|
||||||
|
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||||
|
source.put("foo.name", "invalid");
|
||||||
|
source.put("foo.counter", "42");
|
||||||
|
this.sources.add(source);
|
||||||
|
ExampleWithStaticAccessors bean = this.binder
|
||||||
|
.bind("foo", Bindable.of(ExampleWithStaticAccessors.class)).get();
|
||||||
|
assertThat(ExampleWithStaticAccessors.name).isNull();
|
||||||
|
assertThat(bean.getCounter()).isEqualTo(42);
|
||||||
|
}
|
||||||
|
|
||||||
public static class ExampleValueBean {
|
public static class ExampleValueBean {
|
||||||
|
|
||||||
private int intValue;
|
private int intValue;
|
||||||
|
@ -845,6 +857,30 @@ public class JavaBeanBinderTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ExampleWithStaticAccessors {
|
||||||
|
|
||||||
|
private static String name;
|
||||||
|
|
||||||
|
private int counter;
|
||||||
|
|
||||||
|
public static String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setName(String name) {
|
||||||
|
ExampleWithStaticAccessors.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCounter() {
|
||||||
|
return this.counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCounter(int counter) {
|
||||||
|
this.counter = counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public enum ExampleEnum {
|
public enum ExampleEnum {
|
||||||
|
|
||||||
FOO_BAR,
|
FOO_BAR,
|
||||||
|
|
Loading…
Reference in New Issue