From 4d3a899a53c6842a9dccede91170c25f90dc4451 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 19 Jul 2018 11:58:42 +0200 Subject: [PATCH] OrderUtils caches order values (for AnnotationAwareOrderComparator) Issue: SPR-17064 (cherry picked from commit d0bbbf4) --- .../core/annotation/OrderUtils.java | 49 ++++++++++++++----- .../core/annotation/OrderUtilsTests.java | 11 ++++- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java index e0ad41074a..6642f8fc9e 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/OrderUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,9 +17,11 @@ package org.springframework.core.annotation; import java.lang.annotation.Annotation; +import java.util.Map; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; +import org.springframework.util.ConcurrentReferenceHashMap; /** * General utility for determining the order of an object based on its type declaration. @@ -34,6 +36,10 @@ import org.springframework.util.ClassUtils; @SuppressWarnings("unchecked") public abstract class OrderUtils { + /** Cache marker for a non-annotated Class */ + private static final Object NOT_ANNOTATED = new Object(); + + @Nullable private static Class priorityAnnotationType; @@ -49,6 +55,13 @@ public abstract class OrderUtils { } + /** Cache for @Order value (or NOT_ANNOTATED marker) per Class */ + private static final Map, Object> orderCache = new ConcurrentReferenceHashMap<>(64); + + /** Cache for @Priority value (or NOT_ANNOTATED marker) per Class */ + private static final Map, Object> priorityCache = new ConcurrentReferenceHashMap<>(); + + /** * Return the order on the specified {@code type}, or the specified * default value if none can be found. @@ -86,15 +99,20 @@ public abstract class OrderUtils { */ @Nullable public static Integer getOrder(Class type) { + Object cached = orderCache.get(type); + if (cached != null) { + return (cached instanceof Integer ? (Integer) cached : null); + } Order order = AnnotationUtils.findAnnotation(type, Order.class); + Integer result; if (order != null) { - return order.value(); + result = order.value(); } - Integer priorityOrder = getPriority(type); - if (priorityOrder != null) { - return priorityOrder; + else { + result = getPriority(type); } - return null; + orderCache.put(type, (result != null ? result : NOT_ANNOTATED)); + return result; } /** @@ -105,13 +123,20 @@ public abstract class OrderUtils { */ @Nullable public static Integer getPriority(Class type) { - if (priorityAnnotationType != null) { - Annotation priority = AnnotationUtils.findAnnotation(type, priorityAnnotationType); - if (priority != null) { - return (Integer) AnnotationUtils.getValue(priority); - } + if (priorityAnnotationType == null) { + return null; + } + Object cached = priorityCache.get(type); + if (cached != null) { + return (cached instanceof Integer ? (Integer) cached : null); + } + Annotation priority = AnnotationUtils.findAnnotation(type, priorityAnnotationType); + Integer result = null; + if (priority != null) { + result = (Integer) AnnotationUtils.getValue(priority); } - return null; + priorityCache.put(type, (result != null ? result : NOT_ANNOTATED)); + return result; } } diff --git a/spring-core/src/test/java/org/springframework/core/annotation/OrderUtilsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/OrderUtilsTests.java index 850e792b6e..81442faf37 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/OrderUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/OrderUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,41 +23,48 @@ import org.junit.Test; import static org.junit.Assert.*; /** - * * @author Stephane Nicoll + * @author Juergen Hoeller */ public class OrderUtilsTests { @Test public void getSimpleOrder() { assertEquals(Integer.valueOf(50), OrderUtils.getOrder(SimpleOrder.class, null)); + assertEquals(Integer.valueOf(50), OrderUtils.getOrder(SimpleOrder.class, null)); } @Test public void getPriorityOrder() { assertEquals(Integer.valueOf(55), OrderUtils.getOrder(SimplePriority.class, null)); + assertEquals(Integer.valueOf(55), OrderUtils.getOrder(SimplePriority.class, null)); } @Test public void getOrderWithBoth() { assertEquals(Integer.valueOf(50), OrderUtils.getOrder(OrderAndPriority.class, null)); + assertEquals(Integer.valueOf(50), OrderUtils.getOrder(OrderAndPriority.class, null)); } @Test public void getDefaultOrder() { assertEquals(33, OrderUtils.getOrder(NoOrder.class, 33)); + assertEquals(33, OrderUtils.getOrder(NoOrder.class, 33)); } @Test public void getPriorityValueNoAnnotation() { assertNull(OrderUtils.getPriority(SimpleOrder.class)); + assertNull(OrderUtils.getPriority(SimpleOrder.class)); } @Test public void getPriorityValue() { assertEquals(Integer.valueOf(55), OrderUtils.getPriority(OrderAndPriority.class)); + assertEquals(Integer.valueOf(55), OrderUtils.getPriority(OrderAndPriority.class)); } + @Order(50) private static class SimpleOrder {}