Optimize property sources pattern matching
Create a PropertyNamePatternsMatcher strategy interface that PropertySourcesPropertyValues can use to determine when a property can be used. PropertiesConfigurationFactory uses DefaultPropertyNamePatternsMatcher which is heavily optimized for frequent calls. Fixes gh-1823pull/1783/merge
parent
adffb7a30f
commit
f5a52ddd5a
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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.bind;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Default {@link PropertyNamePatternsMatcher} that matches when a property name exactly
|
||||
* matches one of the given names, or starts with one of the given names followed by '.'
|
||||
* or '_'. This implementation is optimized for frequent calls.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 1.2.0
|
||||
*/
|
||||
class DefaultPropertyNamePatternsMatcher implements PropertyNamePatternsMatcher {
|
||||
|
||||
private final String[] names;
|
||||
|
||||
public DefaultPropertyNamePatternsMatcher(String... names) {
|
||||
this(new HashSet<String>(Arrays.asList(names)));
|
||||
}
|
||||
|
||||
public DefaultPropertyNamePatternsMatcher(Set<String> names) {
|
||||
this.names = names.toArray(new String[names.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(String propertyName) {
|
||||
char[] propertNameChars = propertyName.toCharArray();
|
||||
boolean[] match = new boolean[this.names.length];
|
||||
boolean noneMatched = true;
|
||||
for (int i = 0; i < this.names.length; i++) {
|
||||
if (this.names[i].length() <= propertNameChars.length) {
|
||||
match[i] = true;
|
||||
noneMatched = false;
|
||||
}
|
||||
}
|
||||
if (noneMatched) {
|
||||
return false;
|
||||
}
|
||||
for (int charIndex = 0; charIndex < propertNameChars.length; charIndex++) {
|
||||
noneMatched = true;
|
||||
for (int nameIndex = 0; nameIndex < this.names.length; nameIndex++) {
|
||||
if (match[nameIndex]) {
|
||||
if (charIndex < this.names[nameIndex].length()) {
|
||||
if (this.names[nameIndex].charAt(charIndex) == propertNameChars[charIndex]) {
|
||||
match[nameIndex] = true;
|
||||
noneMatched = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
char charAfter = propertNameChars[this.names[nameIndex].length()];
|
||||
if (charAfter == '.' || charAfter == '_') {
|
||||
match[nameIndex] = true;
|
||||
noneMatched = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (noneMatched) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < match.length; i++) {
|
||||
if (match[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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.bind;
|
||||
|
||||
/**
|
||||
* Strategy interface used to check if a property name matches specific criteria.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 1.2.0
|
||||
*/
|
||||
interface PropertyNamePatternsMatcher {
|
||||
|
||||
PropertyNamePatternsMatcher NONE = new PropertyNamePatternsMatcher() {
|
||||
|
||||
@Override
|
||||
public boolean matches(String propertyName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Return {@code true} of the property name matches.
|
||||
* @param propertyName the property name
|
||||
* @return {@code true} if the property name matches
|
||||
*/
|
||||
boolean matches(String propertyName);
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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.bind;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
|
||||
/**
|
||||
* {@link PropertyNamePatternsMatcher} that delegates to
|
||||
* {@link PatternMatchUtils#simpleMatch(String[], String)}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 1.2.0
|
||||
*/
|
||||
class SimplePropertyNamePatternsMatcher implements PropertyNamePatternsMatcher {
|
||||
|
||||
private final String[] patterns;
|
||||
|
||||
public SimplePropertyNamePatternsMatcher(Collection<String> patterns) {
|
||||
this.patterns = (patterns == null ? new String[] {} : patterns
|
||||
.toArray(new String[patterns.size()]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(String propertyName) {
|
||||
return PatternMatchUtils.simpleMatch(this.patterns, propertyName);
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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.bind;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Tests for {@link DefaultPropertyNamePatternsMatcher}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class DefaultPropertyNamePatternsMatcherTests {
|
||||
|
||||
@Test
|
||||
public void namesShorter() {
|
||||
assertFalse(new DefaultPropertyNamePatternsMatcher("aaaa", "bbbb")
|
||||
.matches("zzzzz"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void namesExactMatch() {
|
||||
assertTrue(new DefaultPropertyNamePatternsMatcher("aaaa", "bbbb", "cccc")
|
||||
.matches("bbbb"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void namesLonger() {
|
||||
assertFalse(new DefaultPropertyNamePatternsMatcher("aaaaa", "bbbbb", "ccccc")
|
||||
.matches("bbbb"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nameWithDot() throws Exception {
|
||||
assertTrue(new DefaultPropertyNamePatternsMatcher("aaaa", "bbbb", "cccc")
|
||||
.matches("bbbb.anything"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nameWithUnderscore() throws Exception {
|
||||
assertTrue(new DefaultPropertyNamePatternsMatcher("aaaa", "bbbb", "cccc")
|
||||
.matches("bbbb_anything"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void namesMatchWithDifferentLengths() throws Exception {
|
||||
assertTrue(new DefaultPropertyNamePatternsMatcher("aaa", "bbbb", "ccccc")
|
||||
.matches("bbbb"));
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue