#977 - Performance improvements in link generation.

Introduced more caches for reusable value objects: UriTemplate, MethodParameters. Cache UriTemplate.toString() to avoid re-computation. Avoid recomputing the affordances if possible in WebHandler. Removed cache in AnnotatedParametersParameterAccessor as that one now transitively benefits from the one introduced in MethodParameters.

Related ticket: spring-projects/spring-framework#22730.
This commit is contained in:
Oliver Drotbohm
2019-04-03 18:31:46 +02:00
parent fc3767b90b
commit 39404ea2d9
15 changed files with 152 additions and 137 deletions

View File

@@ -22,6 +22,7 @@ import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -46,7 +47,10 @@ public class UriTemplate implements Iterable<TemplateVariable>, Serializable {
private static final Pattern VARIABLE_REGEX = Pattern.compile("\\{([\\?\\&#/]?)([\\w\\,*]+)\\}");
private static final long serialVersionUID = -1007874653930162262L;
private static final Map<String, UriTemplate> CACHE = new ConcurrentHashMap<>();
private final TemplateVariables variables;
private String toString;
private String baseUri;
/**
@@ -54,7 +58,7 @@ public class UriTemplate implements Iterable<TemplateVariable>, Serializable {
*
* @param template must not be {@literal null} or empty.
*/
public UriTemplate(String template) {
private UriTemplate(String template) {
Assert.hasText(template, "Template must not be null or empty!");
@@ -97,7 +101,7 @@ public class UriTemplate implements Iterable<TemplateVariable>, Serializable {
* @param baseUri must not be {@literal null} or empty.
* @param variables must not be {@literal null}.
*/
public UriTemplate(String baseUri, TemplateVariables variables) {
UriTemplate(String baseUri, TemplateVariables variables) {
Assert.hasText(baseUri, "Base URI must not be null or empty!");
Assert.notNull(variables, "Template variables must not be null!");
@@ -106,6 +110,19 @@ public class UriTemplate implements Iterable<TemplateVariable>, Serializable {
this.variables = variables;
}
/**
* Returns a {@link UriTemplate} for the given {@link String} template.
*
* @param template must not be {@literal null} or empty.
* @return
*/
public static UriTemplate of(String template) {
Assert.hasText(template, "Template must not be null or empty!");
return CACHE.computeIfAbsent(template, UriTemplate::new);
}
/**
* Creates a new {@link UriTemplate} with the current {@link TemplateVariable}s augmented with the given ones.
*
@@ -267,10 +284,15 @@ public class UriTemplate implements Iterable<TemplateVariable>, Serializable {
@Override
public String toString() {
UriComponents components = UriComponentsBuilder.fromUriString(baseUri).build();
boolean hasQueryParameters = !components.getQueryParams().isEmpty();
if (toString == null) {
return baseUri + getOptionalVariables().toString(hasQueryParameters);
UriComponents components = UriComponentsBuilder.fromUriString(baseUri).build();
boolean hasQueryParameters = !components.getQueryParams().isEmpty();
this.toString = baseUri + getOptionalVariables().toString(hasQueryParameters);
}
return toString;
}
private TemplateVariables getOptionalVariables() {