Commit 001f2d6c authored by Phillip Webb's avatar Phillip Webb

Improve performance of MessageSource condition

Update the MessageSourceAutoConfiguration condition to skip scanning for
well known JARs. Results are now also cached.

Fixes gh-1689
parent 828efb25
......@@ -17,6 +17,8 @@
package org.springframework.boot.autoconfigure;
import java.io.IOException;
import java.util.Iterator;
import java.util.Set;
import org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration.ResourceBundleCondition;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
......@@ -35,6 +37,7 @@ import org.springframework.core.annotation.Order;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.StringUtils;
import static org.springframework.util.StringUtils.commaDelimitedListToStringArray;
......@@ -44,6 +47,7 @@ import static org.springframework.util.StringUtils.trimAllWhitespace;
* {@link EnableAutoConfiguration Auto-configuration} for {@link MessageSource}.
*
* @author Dave Syer
* @author Phillip Webb
*/
@Configuration
@ConditionalOnMissingBean(MessageSource.class)
......@@ -99,11 +103,23 @@ public class MessageSourceAutoConfiguration {
protected static class ResourceBundleCondition extends SpringBootCondition {
private static ConcurrentReferenceHashMap<String, ConditionOutcome> cache = new ConcurrentReferenceHashMap<String, ConditionOutcome>();
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
String basename = context.getEnvironment().getProperty(
"spring.messages.basename", "messages");
ConditionOutcome outcome = cache.get(basename);
if (outcome == null) {
outcome = getMatchOutcomeForBasename(context, basename);
cache.put(basename, outcome);
}
return outcome;
}
private ConditionOutcome getMatchOutcomeForBasename(ConditionContext context,
String basename) {
for (String name : commaDelimitedListToStringArray(trimAllWhitespace(basename))) {
for (Resource resource : getResources(context.getClassLoader(), name)) {
if (resource.exists()) {
......@@ -118,7 +134,7 @@ public class MessageSourceAutoConfiguration {
private Resource[] getResources(ClassLoader classLoader, String name) {
try {
return new PathMatchingResourcePatternResolver(classLoader)
return new SkipPatternPathMatchingResourcePatternResolver(classLoader)
.getResources("classpath*:" + name + "*.properties");
}
catch (IOException ex) {
......@@ -128,4 +144,60 @@ public class MessageSourceAutoConfiguration {
}
/**
* {@link PathMatchingResourcePatternResolver} that skips well known JARs that don't
* contain messages.properties.
*/
private static class SkipPatternPathMatchingResourcePatternResolver extends
PathMatchingResourcePatternResolver {
private static final ClassLoader ROOT_CLASSLOADER;
static {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
while (classLoader.getParent() != null) {
classLoader = classLoader.getParent();
}
ROOT_CLASSLOADER = classLoader;
}
private static final String[] SKIPPED = { "aspectjweaver-", "hibernate-core-",
"hsqldb-", "jackson-annotations-", "jackson-core-", "jackson-databind-",
"javassist-", "snakeyaml-", "spring-aop-", "spring-beans-",
"spring-boot-", "spring-boot-actuator-", "spring-boot-autoconfigure-",
"spring-core-", "spring-context-", "spring-data-commons-",
"spring-expression-", "spring-jdbc-", "spring-orm-", "spring-tx-",
"spring-web-", "spring-webmvc-", "tomcat-embed-", "joda-time-",
"hibernate-entitymanager-", "hibernate-validator-", "logback-classic-",
"logback-core-", "thymeleaf-" };
public SkipPatternPathMatchingResourcePatternResolver(ClassLoader classLoader) {
super(classLoader);
}
@Override
protected void addAllClassLoaderJarRoots(ClassLoader classLoader,
Set<Resource> result) {
if (classLoader != ROOT_CLASSLOADER) {
super.addAllClassLoaderJarRoots(classLoader, result);
}
};
@Override
protected Set<Resource> doFindAllClassPathResources(String path)
throws IOException {
Set<Resource> resources = super.doFindAllClassPathResources(path);
for (Iterator<Resource> iterator = resources.iterator(); iterator.hasNext();) {
Resource resource = iterator.next();
for (String skipped : SKIPPED) {
if (resource.getFilename().startsWith(skipped)) {
iterator.remove();
break;
}
}
}
return resources;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment