mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Merge branch '7.0.x'
This commit is contained in:
@@ -9,7 +9,7 @@ javaPlatform {
|
||||
dependencies {
|
||||
api(platform("com.fasterxml.jackson:jackson-bom:2.20.2"))
|
||||
api(platform("io.micrometer:micrometer-bom:1.16.4"))
|
||||
api(platform("io.netty:netty-bom:4.2.10.Final"))
|
||||
api(platform("io.netty:netty-bom:4.2.12.Final"))
|
||||
api(platform("io.projectreactor:reactor-bom:2025.0.4"))
|
||||
api(platform("io.rsocket:rsocket-bom:1.1.5"))
|
||||
api(platform("org.apache.groovy:groovy-bom:5.0.4"))
|
||||
|
||||
+10
@@ -193,8 +193,18 @@ public @interface Cacheable {
|
||||
* This is effectively a hint and the chosen cache provider might not actually
|
||||
* support it in a synchronized fashion. Check your provider documentation for
|
||||
* more details on the actual semantics.
|
||||
* <p>Note that `sync=true` leads to a combined callback operation against the
|
||||
* cache provider. If this combined operation fails on initial cache access,
|
||||
* there is no separate put operation to attempt anymore. Whereas for a default
|
||||
* `sync=false` setup, there are independent get and put steps: If the get step
|
||||
* fails but its error is suppressed in the {@code CacheErrorHandler} setup,
|
||||
* there will still be a put attempt after calling the underlying method.
|
||||
* @since 4.3
|
||||
* @see org.springframework.cache.Cache#get(Object, Callable)
|
||||
* @see org.springframework.cache.Cache#get(Object)
|
||||
* @see org.springframework.cache.Cache#put(Object, Object)
|
||||
* @see org.springframework.cache.interceptor.CacheErrorHandler#handleCacheGetError
|
||||
* @see org.springframework.cache.interceptor.CacheErrorHandler#handleCachePutError
|
||||
*/
|
||||
boolean sync() default false;
|
||||
|
||||
|
||||
+9
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.cache.interceptor;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
@@ -39,10 +41,17 @@ public interface CacheErrorHandler {
|
||||
* Handle the given runtime exception thrown by the cache provider when
|
||||
* retrieving an item with the specified {@code key}, possibly
|
||||
* rethrowing it as a fatal exception.
|
||||
* <p>Note that for a default {@code @Cacheable} setup, this will be called
|
||||
* after an initial cache access failure, whereas the subsequent put step may
|
||||
* independently fail and be handled in {@link #handleCachePutError} still.
|
||||
* However, for {@code @Cacheable(sync=true)}, there is only a combined get step
|
||||
* with {@code handleCacheGetError} being called in case of failure; there won't
|
||||
* be a separate put attempt after initial cache access failure anymore.
|
||||
* @param exception the exception thrown by the cache provider
|
||||
* @param cache the cache
|
||||
* @param key the key used to get the item
|
||||
* @see Cache#get(Object)
|
||||
* @see Cache#get(Object, Callable)
|
||||
*/
|
||||
void handleCacheGetError(RuntimeException exception, Cache cache, Object key);
|
||||
|
||||
|
||||
+38
-39
@@ -126,10 +126,10 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
}
|
||||
|
||||
private static List<ResolvableType> resolveDeclaredEventTypes(Method method, @Nullable EventListener ann) {
|
||||
int count = (KotlinDetector.isSuspendingFunction(method) ? method.getParameterCount() - 1 : method.getParameterCount());
|
||||
int count = (KotlinDetector.isSuspendingFunction(method) ? method.getParameterCount() - 1 :
|
||||
method.getParameterCount());
|
||||
if (count > 1) {
|
||||
throw new IllegalStateException(
|
||||
"Maximum one parameter is allowed for event listener method: " + method);
|
||||
throw new IllegalStateException("Maximum one parameter is allowed for event listener method: " + method);
|
||||
}
|
||||
|
||||
if (ann != null) {
|
||||
@@ -156,6 +156,35 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the target listener method.
|
||||
* @since 7.0.7 in public form (with protected visibility since 5.3)
|
||||
*/
|
||||
public final Method getTargetMethod() {
|
||||
return this.targetMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the condition to use.
|
||||
* <p>Matches the {@code condition} attribute of the {@link EventListener}
|
||||
* annotation or any matching attribute on a composed annotation that
|
||||
* is meta-annotated with {@code @EventListener}.
|
||||
*/
|
||||
protected final @Nullable String getCondition() {
|
||||
return this.condition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether default execution is applicable for the target listener.
|
||||
* @since 6.2
|
||||
* @see #onApplicationEvent
|
||||
* @see EventListener#defaultExecution()
|
||||
*/
|
||||
protected final boolean isDefaultExecution() {
|
||||
return this.defaultExecution;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize this instance.
|
||||
*/
|
||||
@@ -167,7 +196,7 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if (isDefaultExecution()) {
|
||||
if (this.defaultExecution) {
|
||||
processEvent(event);
|
||||
}
|
||||
}
|
||||
@@ -222,22 +251,11 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
* @see #getListenerId()
|
||||
*/
|
||||
protected String getDefaultListenerId() {
|
||||
Method method = getTargetMethod();
|
||||
StringJoiner sj = new StringJoiner(",", "(", ")");
|
||||
for (Class<?> paramType : method.getParameterTypes()) {
|
||||
for (Class<?> paramType : this.targetMethod.getParameterTypes()) {
|
||||
sj.add(paramType.getName());
|
||||
}
|
||||
return ClassUtils.getQualifiedMethodName(method) + sj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether default execution is applicable for the target listener.
|
||||
* @since 6.2
|
||||
* @see #onApplicationEvent
|
||||
* @see EventListener#defaultExecution()
|
||||
*/
|
||||
protected boolean isDefaultExecution() {
|
||||
return this.defaultExecution;
|
||||
return ClassUtils.getQualifiedMethodName(this.targetMethod) + sj;
|
||||
}
|
||||
|
||||
|
||||
@@ -274,11 +292,10 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
if (args == null) {
|
||||
return false;
|
||||
}
|
||||
String condition = getCondition();
|
||||
if (StringUtils.hasText(condition)) {
|
||||
if (StringUtils.hasText(this.condition)) {
|
||||
Assert.notNull(this.evaluator, "EventExpressionEvaluator must not be null");
|
||||
return this.evaluator.condition(
|
||||
condition, event, this.targetMethod, this.methodKey, args);
|
||||
this.condition, event, this.targetMethod, this.methodKey, args);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -402,24 +419,6 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
return this.applicationContext.getBean(this.beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the target listener method.
|
||||
* @since 5.3
|
||||
*/
|
||||
protected Method getTargetMethod() {
|
||||
return this.targetMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the condition to use.
|
||||
* <p>Matches the {@code condition} attribute of the {@link EventListener}
|
||||
* annotation or any matching attribute on a composed annotation that
|
||||
* is meta-annotated with {@code @EventListener}.
|
||||
*/
|
||||
protected @Nullable String getCondition() {
|
||||
return this.condition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add additional details such as the bean type and method signature to
|
||||
* the given error message.
|
||||
@@ -427,7 +426,7 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
||||
*/
|
||||
protected String getDetailedErrorMessage(Object bean, @Nullable String message) {
|
||||
StringBuilder sb = (StringUtils.hasLength(message) ? new StringBuilder(message).append('\n') : new StringBuilder());
|
||||
sb.append("HandlerMethod details: \n");
|
||||
sb.append("ApplicationListenerMethodAdapter details: \n");
|
||||
sb.append("Bean [").append(bean.getClass().getName()).append("]\n");
|
||||
sb.append("Method [").append(this.method.toGenericString()).append("]\n");
|
||||
return sb.toString();
|
||||
|
||||
+1
-2
@@ -324,8 +324,7 @@ public class SimpleAsyncTaskExecutor extends CustomizableThreadCreator
|
||||
catch (Throwable ex) {
|
||||
// Release concurrency permit if thread creation fails
|
||||
this.concurrencyThrottle.afterAccess();
|
||||
throw new TaskRejectedException(
|
||||
"Failed to start execution thread for task: " + task, ex);
|
||||
throw new TaskRejectedException("Failed to start execution thread for task: " + task, ex);
|
||||
}
|
||||
}
|
||||
else if (this.activeThreads != null) {
|
||||
|
||||
-1
@@ -42,7 +42,6 @@ import org.springframework.util.Assert;
|
||||
* @see java.util.concurrent.ExecutorService
|
||||
* @see java.util.concurrent.Executors
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class TaskExecutorAdapter implements AsyncTaskExecutor {
|
||||
|
||||
private final Executor concurrentExecutor;
|
||||
|
||||
+1
-6
@@ -105,7 +105,6 @@ final class SseServerResponse extends AbstractServerResponse {
|
||||
|
||||
private static final byte[] NL_NL = new byte[]{'\n', '\n'};
|
||||
|
||||
|
||||
private final ServerHttpResponse outputMessage;
|
||||
|
||||
private final DeferredResult<?> deferredResult;
|
||||
@@ -118,7 +117,6 @@ final class SseServerResponse extends AbstractServerResponse {
|
||||
|
||||
private boolean sendFailed;
|
||||
|
||||
|
||||
public DefaultSseBuilder(HttpServletResponse response, Context context, DeferredResult<?> deferredResult,
|
||||
HttpHeaders httpHeaders) {
|
||||
this.outputMessage = new ServletServerHttpResponse(response);
|
||||
@@ -184,7 +182,6 @@ final class SseServerResponse extends AbstractServerResponse {
|
||||
@Override
|
||||
public void data(Object object) throws IOException {
|
||||
Assert.notNull(object, "Object must not be null");
|
||||
|
||||
if (object instanceof String text) {
|
||||
writeString(text);
|
||||
}
|
||||
@@ -206,7 +203,6 @@ final class SseServerResponse extends AbstractServerResponse {
|
||||
this.builder.append("data:");
|
||||
try {
|
||||
this.outputMessage.getBody().write(builderBytes());
|
||||
|
||||
Class<?> dataClass = data.getClass();
|
||||
for (HttpMessageConverter<?> converter : this.messageConverters) {
|
||||
if (converter.canWrite(dataClass, MediaType.APPLICATION_JSON)) {
|
||||
@@ -291,8 +287,7 @@ final class SseServerResponse extends AbstractServerResponse {
|
||||
public HttpHeaders getHeaders() {
|
||||
return this.mutableHeaders;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user