diff --git a/spring-context/src/main/java/org/springframework/validation/DefaultBindingErrorProcessor.java b/spring-context/src/main/java/org/springframework/validation/DefaultBindingErrorProcessor.java index dd1b3e18695..ebe16fb2f66 100644 --- a/spring-context/src/main/java/org/springframework/validation/DefaultBindingErrorProcessor.java +++ b/spring-context/src/main/java/org/springframework/validation/DefaultBindingErrorProcessor.java @@ -18,10 +18,9 @@ package org.springframework.validation; import java.io.Serializable; -import org.jspecify.annotations.Nullable; - import org.springframework.beans.PropertyAccessException; import org.springframework.context.support.DefaultMessageSourceResolvable; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; diff --git a/spring-core/src/main/java/org/springframework/util/ConcurrentLruCache.java b/spring-core/src/main/java/org/springframework/util/ConcurrentLruCache.java index a619240ec3e..78342891b34 100644 --- a/spring-core/src/main/java/org/springframework/util/ConcurrentLruCache.java +++ b/spring-core/src/main/java/org/springframework/util/ConcurrentLruCache.java @@ -32,9 +32,11 @@ import org.springframework.lang.Nullable; /** * Simple LRU (Least Recently Used) cache, bounded by a specified cache capacity. + * *
This is a simplified, opinionated implementation of an LRU cache for internal * use in Spring Framework. It is inspired from * ConcurrentLinkedHashMap. + * *
Read and write operations are internally recorded in dedicated buffers,
* then drained at chosen times to avoid contention.
*
@@ -70,6 +72,7 @@ public final class ConcurrentLruCache {@link ErrorResponseException} is a default implementation of this
* interface and a convenient base class for other exceptions to use.
*
* {@code ErrorResponse} is supported as a return value from
- * {@code @ExceptionHandler} methods that render directly to the response, for example,
- * by being marked {@code @ResponseBody}, or declared in an
+ * {@code @ExceptionHandler} methods that render directly to the response,
+ * for example, by being marked {@code @ResponseBody}, or declared in an
* {@code @RestController} or {@code RestControllerAdvice} class.
*
* @author Rossen Stoyanchev
diff --git a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java
index 32423044ed3..15af91993e3 100644
--- a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java
+++ b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java
@@ -96,7 +96,7 @@ public class HandlerMethod extends AnnotatedMethod {
@Nullable
private HandlerMethod resolvedFromHandlerMethod;
- private @Nullable HandlerMethod resolvedBeanHandlerMethod;
+ private volatile @Nullable HandlerMethod resolvedBeanHandlerMethod;
private final String description;
@@ -196,16 +196,21 @@ public class HandlerMethod extends AnnotatedMethod {
this.beanFactory = handlerMethod.beanFactory;
this.messageSource = handlerMethod.messageSource;
this.beanType = handlerMethod.beanType;
+
this.validateArguments = (initValidateFlags ?
MethodValidationInitializer.checkArguments(this.beanType, getMethodParameters()) :
handlerMethod.validateArguments);
+
this.validateReturnValue = (initValidateFlags ?
MethodValidationInitializer.checkReturnValue(this.beanType, getBridgedMethod()) :
handlerMethod.validateReturnValue);
+
this.responseStatus = handlerMethod.responseStatus;
this.responseStatusReason = handlerMethod.responseStatusReason;
+
this.resolvedFromHandlerMethod = (handlerMethod.resolvedFromHandlerMethod != null ?
handlerMethod.resolvedFromHandlerMethod : handlerMethod);
+
this.description = handlerMethod.toString();
}
@@ -224,7 +229,10 @@ public class HandlerMethod extends AnnotatedMethod {
this.responseStatus = annotation.code();
this.responseStatusReason = resolvedReason;
if (StringUtils.hasText(this.responseStatusReason) && getMethod().getReturnType() != void.class) {
- logger.warn("Return value of [" + getMethod() + "] will be ignored since @ResponseStatus 'reason' attribute is set.");
+ if (logger.isWarnEnabled()) {
+ logger.warn("Return value of [" + getMethod() +
+ "] will be ignored since @ResponseStatus 'reason' attribute is set.");
+ }
}
}
}
@@ -334,23 +342,22 @@ public class HandlerMethod extends AnnotatedMethod {
* If the {@link #getBean() handler} is not String, return the same instance.
*/
public HandlerMethod createWithResolvedBean() {
- if (this.resolvedBeanHandlerMethod != null) {
- return this.resolvedBeanHandlerMethod;
+ HandlerMethod resolvedBeanHandlerMethod = this.resolvedBeanHandlerMethod;
+ if (resolvedBeanHandlerMethod != null) {
+ return resolvedBeanHandlerMethod;
}
+ // We need to resolve a bean name reference.
if (!(this.bean instanceof String beanName)) {
return this;
}
-
Assert.state(this.beanFactory != null, "Cannot resolve bean name without BeanFactory");
Object handler = this.beanFactory.getBean(beanName);
- Assert.notNull(handler, "No handler instance");
HandlerMethod handlerMethod = new HandlerMethod(this, handler, false);
if (this.beanFactory.isSingleton(beanName)) {
this.resolvedBeanHandlerMethod = handlerMethod;
}
-
return handlerMethod;
}
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java
index f939d997abf..cd5414683cf 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java
@@ -209,7 +209,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
/**
* Configure the list of {@link ResourceResolver ResourceResolvers} to use.
- * By default {@link PathResourceResolver} is configured. If using this property,
+ * By default, {@link PathResourceResolver} is configured. If using this property,
* it is recommended to add {@link PathResourceResolver} as the last resolver.
*/
public void setResourceResolvers(@Nullable List By default no transformers are configured for use.
+ * By default, no transformers are configured for use.
*/
public void setResourceTransformers(@Nullable List By default a {@link ResourceHttpMessageConverter} will be configured.
+ * By default, a {@link ResourceHttpMessageConverter} will be configured.
* @since 4.3
*/
public void setResourceHttpMessageConverter(@Nullable ResourceHttpMessageConverter messageConverter) {
@@ -264,7 +264,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
/**
* Configure the {@link ResourceRegionHttpMessageConverter} to use.
- * By default a {@link ResourceRegionHttpMessageConverter} will be configured.
+ * By default, a {@link ResourceRegionHttpMessageConverter} will be configured.
* @since 4.3
*/
public void setResourceRegionHttpMessageConverter(@Nullable ResourceRegionHttpMessageConverter messageConverter) {
@@ -331,7 +331,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
/**
* Specify the CORS configuration for resources served by this handler.
- * By default this is not set in which allows cross-origin requests.
+ * By default, this is not set in which allows cross-origin requests.
*/
public void setCorsConfiguration(CorsConfiguration corsConfiguration) {
this.corsConfiguration = corsConfiguration;
@@ -581,7 +581,6 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
// For very general mappings (for example, "/") we need to check 404 first
Resource resource = getResource(request);
if (resource == null) {
- logger.debug("Resource not found");
throw new NoResourceFoundException(HttpMethod.valueOf(request.getMethod()), getPath(request));
}
@@ -597,10 +596,12 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
prepareResponse(response);
// Header phase
- String eTagValue = (getEtagGenerator() != null ? getEtagGenerator().apply(resource) : null);
+ String etagValue = (getEtagGenerator() != null ? getEtagGenerator().apply(resource) : null);
long lastModified = (isUseLastModified() ? resource.lastModified() : -1);
- if (new ServletWebRequest(request, response).checkNotModified(eTagValue, lastModified)) {
- logger.trace("Resource not modified");
+ if (new ServletWebRequest(request, response).checkNotModified(etagValue, lastModified)) {
+ if (logger.isTraceEnabled()) {
+ logger.trace("Resource not modified: " + resource);
+ }
return;
}
@@ -611,8 +612,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
// Content phase
ServletServerHttpResponse outputMessage = new ServletServerHttpResponse(response);
if (request.getHeader(HttpHeaders.RANGE) == null) {
- Assert.state(this.resourceHttpMessageConverter != null, "Not initialized");
-
+ Assert.state(this.resourceHttpMessageConverter != null, "Converter not initialized");
if (HttpMethod.HEAD.matches(request.getMethod())) {
this.resourceHttpMessageConverter.addDefaultHeaders(outputMessage, resource, mediaType);
outputMessage.flush();
@@ -622,7 +622,7 @@ public class ResourceHttpRequestHandler extends WebContentGenerator
}
}
else {
- Assert.state(this.resourceRegionHttpMessageConverter != null, "Not initialized");
+ Assert.state(this.resourceRegionHttpMessageConverter != null, "Converter not initialized");
ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(request);
try {
List