2
0
Эх сурвалжийг харах

Cache Annotation Lookups

Closes gh-15799
Josh Cummings 11 сар өмнө
parent
commit
1760e7fac8

+ 15 - 4
core/src/main/java/org/springframework/security/core/annotation/SecurityAnnotationScanners.java

@@ -19,7 +19,9 @@ package org.springframework.security.core.annotation;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.AnnotatedElement;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Factory for creating {@link SecurityAnnotationScanner} instances.
@@ -29,6 +31,12 @@ import java.util.List;
  */
 public final class SecurityAnnotationScanners {
 
+	private static final Map<Class<? extends Annotation>, SecurityAnnotationScanner<? extends Annotation>> uniqueScanners = new HashMap<>();
+
+	private static final Map<Class<? extends Annotation>, SecurityAnnotationScanner<? extends Annotation>> uniqueTemplateScanners = new HashMap<>();
+
+	private static final Map<List<Class<? extends Annotation>>, SecurityAnnotationScanner<? extends Annotation>> uniqueTypesScanners = new HashMap<>();
+
 	private SecurityAnnotationScanners() {
 	}
 
@@ -40,7 +48,8 @@ public final class SecurityAnnotationScanners {
 	 * @return the default {@link SecurityAnnotationScanner}
 	 */
 	public static <A extends Annotation> SecurityAnnotationScanner<A> requireUnique(Class<A> type) {
-		return new UniqueSecurityAnnotationScanner<>(type);
+		return (SecurityAnnotationScanner<A>) uniqueScanners.computeIfAbsent(type,
+				(t) -> new UniqueSecurityAnnotationScanner<>(type));
 	}
 
 	/**
@@ -60,9 +69,10 @@ public final class SecurityAnnotationScanners {
 	public static <A extends Annotation> SecurityAnnotationScanner<A> requireUnique(Class<A> type,
 			AnnotationTemplateExpressionDefaults templateDefaults) {
 		if (templateDefaults == null) {
-			return new UniqueSecurityAnnotationScanner<>(type);
+			return requireUnique(type);
 		}
-		return new ExpressionTemplateSecurityAnnotationScanner<>(type, templateDefaults);
+		return (SecurityAnnotationScanner<A>) uniqueTemplateScanners.computeIfAbsent(type,
+				(t) -> new ExpressionTemplateSecurityAnnotationScanner<>(t, templateDefaults));
 	}
 
 	/**
@@ -75,7 +85,8 @@ public final class SecurityAnnotationScanners {
 	public static SecurityAnnotationScanner<Annotation> requireUnique(List<Class<? extends Annotation>> types) {
 		List<Class<Annotation>> casted = new ArrayList<>();
 		types.forEach((type) -> casted.add((Class<Annotation>) type));
-		return new UniqueSecurityAnnotationScanner<>(casted);
+		return (SecurityAnnotationScanner<Annotation>) uniqueTypesScanners.computeIfAbsent(types,
+				(t) -> new UniqueSecurityAnnotationScanner<>(casted));
 	}
 
 }

+ 15 - 4
core/src/main/java/org/springframework/security/core/annotation/UniqueSecurityAnnotationScanner.java

@@ -22,10 +22,13 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Parameter;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
+import org.springframework.core.MethodClassKey;
 import org.springframework.core.annotation.AnnotationConfigurationException;
 import org.springframework.core.annotation.MergedAnnotation;
 import org.springframework.core.annotation.MergedAnnotations;
@@ -86,6 +89,10 @@ final class UniqueSecurityAnnotationScanner<A extends Annotation> extends Abstra
 
 	private final List<Class<A>> types;
 
+	private final Map<Parameter, MergedAnnotation<A>> uniqueParameterAnnotationCache = new HashMap<>();
+
+	private final Map<MethodClassKey, MergedAnnotation<A>> uniqueMethodAnnotationCache = new HashMap<>();
+
 	UniqueSecurityAnnotationScanner(Class<A> type) {
 		Assert.notNull(type, "type cannot be null");
 		this.types = List.of(type);
@@ -99,12 +106,16 @@ final class UniqueSecurityAnnotationScanner<A extends Annotation> extends Abstra
 	@Override
 	MergedAnnotation<A> merge(AnnotatedElement element, Class<?> targetClass) {
 		if (element instanceof Parameter parameter) {
-			List<MergedAnnotation<A>> annotations = findDirectAnnotations(parameter);
-			return requireUnique(parameter, annotations);
+			return this.uniqueParameterAnnotationCache.computeIfAbsent(parameter, (p) -> {
+				List<MergedAnnotation<A>> annotations = findDirectAnnotations(p);
+				return requireUnique(p, annotations);
+			});
 		}
 		if (element instanceof Method method) {
-			List<MergedAnnotation<A>> annotations = findMethodAnnotations(method, targetClass);
-			return requireUnique(method, annotations);
+			return this.uniqueMethodAnnotationCache.computeIfAbsent(new MethodClassKey(method, targetClass), (k) -> {
+				List<MergedAnnotation<A>> annotations = findMethodAnnotations(method, targetClass);
+				return requireUnique(method, annotations);
+			});
 		}
 		throw new AnnotationConfigurationException("Unsupported element of type " + element.getClass());
 	}