From cf08a92f3454d8cf33c28c7ac037564cffc51703 Mon Sep 17 00:00:00 2001 From: huangchengxing <841396397@qq.com> Date: Thu, 14 Jul 2022 16:16:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=B1=82=E7=BA=A7=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...nthesizedAnnotationAttributeProcessor.java | 6 +- .../hutool/core/annotation/Hierarchical.java | 155 ++++++++++++++++++ .../SynthesizedAggregateAnnotation.java | 28 +++- .../annotation/SynthesizedAnnotation.java | 32 +--- .../SynthesizedAnnotationSelector.java | 8 +- .../SynthesizedMetaAggregateAnnotation.java | 80 ++++++++- .../AliasAnnotationPostProcessorTest.java | 5 + .../AliasLinkAnnotationPostProcessorTest.java | 5 + ...MirrorLinkAnnotationPostProcessorTest.java | 5 + 9 files changed, 284 insertions(+), 40 deletions(-) create mode 100644 hutool-core/src/main/java/cn/hutool/core/annotation/Hierarchical.java diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/CacheableSynthesizedAnnotationAttributeProcessor.java b/hutool-core/src/main/java/cn/hutool/core/annotation/CacheableSynthesizedAnnotationAttributeProcessor.java index e4596446b..ab7ae9ad6 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/CacheableSynthesizedAnnotationAttributeProcessor.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/CacheableSynthesizedAnnotationAttributeProcessor.java @@ -22,14 +22,14 @@ import java.util.Comparator; public class CacheableSynthesizedAnnotationAttributeProcessor implements SynthesizedAnnotationAttributeProcessor { private final Table, Object> valueCaches = new RowKeyTable<>(); - private final Comparator annotationComparator; + private final Comparator annotationComparator; /** * 创建一个带缓存的注解值选择器 * * @param annotationComparator 注解比较器,排序更靠前的注解将被优先用于获取值 */ - public CacheableSynthesizedAnnotationAttributeProcessor(Comparator annotationComparator) { + public CacheableSynthesizedAnnotationAttributeProcessor(Comparator annotationComparator) { Assert.notNull(annotationComparator, "annotationComparator must not null"); this.annotationComparator = annotationComparator; } @@ -40,7 +40,7 @@ public class CacheableSynthesizedAnnotationAttributeProcessor implements Synthes * 越靠前的越优先被取值。 */ public CacheableSynthesizedAnnotationAttributeProcessor() { - this(SynthesizedAnnotation.DEFAULT_CHILD_PRIORITY_COMPARATOR); + this(Hierarchical.DEFAULT_HIERARCHICAL_COMPARATOR); } @SuppressWarnings("unchecked") diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/Hierarchical.java b/hutool-core/src/main/java/cn/hutool/core/annotation/Hierarchical.java new file mode 100644 index 000000000..00c993822 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/Hierarchical.java @@ -0,0 +1,155 @@ +package cn.hutool.core.annotation; + + +import java.util.Comparator; + +/** + *

描述以一个参照物为对象,存在于该参照物的层级结构中的对象。 + * + *

该对象可通过{@link #getVerticalDistance()}与{@link #getHorizontalDistance()} + * 描述其在以参照物为基点的坐标坐标系中的位置。
+ * 在需要对该接口的实现类进行按优先级排序时,距离{@link #getRoot()}对象越近,则该实现类的优先级越高。 + * 默认提供了{@link #DEFAULT_HIERARCHICAL_COMPARATOR}用于实现该比较规则。
+ * 一般情况下,{@link #getRoot()}返回值相同的对象之间的比较才有意义。 + * + *

此外,还提供了{@link Selector}接口用于根据一定的规则从两个{@link Hierarchical}实现类中选择并返回一个最合适的对象, + * 默认提供了四个实现类: + *

    + *
  • {@link Selector#NEAREST_AND_OLDEST_PRIORITY}: 返回距离根对象更近的对象,当距离一样时优先返回旧对象;
  • + *
  • {@link Selector#NEAREST_AND_NEWEST_PRIORITY}: 返回距离根对象更近的对象,当距离一样时优先返回新对象;
  • + *
  • {@link Selector#FARTHEST_AND_OLDEST_PRIORITY}: 返回距离根对象更远的对象,当距离一样时优先返回旧对象;
  • + *
  • {@link Selector#FARTHEST_AND_NEWEST_PRIORITY}: 返回距离根对象更远的对象,当距离一样时优先返回新对象;
  • + *
+ * + * @author huangchengxing + */ +public interface Hierarchical extends Comparable { + + // ====================== compare ====================== + + /** + * 默认{@link #getHorizontalDistance()}与{@link #getVerticalDistance()}排序的比较器 + */ + Comparator DEFAULT_HIERARCHICAL_COMPARATOR = Comparator + .comparing(Hierarchical::getVerticalDistance) + .thenComparing(Hierarchical::getHorizontalDistance); + + /** + * 按{@link #getVerticalDistance()}和{@link #getHorizontalDistance()}排序 + * + * @param o {@link SynthesizedAnnotation}对象 + * @return 比较值 + */ + @Override + default int compareTo(Hierarchical o) { + return DEFAULT_HIERARCHICAL_COMPARATOR.compare(this, o); + } + + // ====================== hierarchical ====================== + + /** + * 参照物,即坐标为{@code (0, 0)}的对象。 + * 当对象本身即为参照物时,该方法应当返回其本身 + * + * @return 参照物 + */ + Object getRoot(); + + /** + * 获取该对象与参照物的垂直距离。 + * 默认情况下,该距离即为当前对象与参照物之间相隔的层级数。 + * + * @return 合成注解与根对象的垂直距离 + */ + int getVerticalDistance(); + + /** + * 获取该对象与参照物的水平距离。 + * 默认情况下,该距离即为当前对象在与参照物{@link #getVerticalDistance()}相同的情况下条, + * 该对象被扫描到的顺序。 + * + * @return 合成注解与根对象的水平距离 + */ + int getHorizontalDistance(); + + // ====================== selector ====================== + + /** + * {@link Hierarchical}选择器,用于根据一定的规则从两个{@link Hierarchical}实现类中选择并返回一个最合适的对象 + */ + @FunctionalInterface + interface Selector { + + /** + * 返回距离根对象更近的对象,当距离一样时优先返回旧对象 + */ + Selector NEAREST_AND_OLDEST_PRIORITY = new NearestAndOldestPrioritySelector(); + + /** + * 返回距离根对象更近的对象,当距离一样时优先返回新对象 + */ + Selector NEAREST_AND_NEWEST_PRIORITY = new NearestAndNewestPrioritySelector(); + + /** + * 返回距离根对象更远的对象,当距离一样时优先返回旧对象 + */ + Selector FARTHEST_AND_OLDEST_PRIORITY = new FarthestAndOldestPrioritySelector(); + + /** + * 返回距离根对象更远的对象,当距离一样时优先返回新对象 + */ + Selector FARTHEST_AND_NEWEST_PRIORITY = new FarthestAndNewestPrioritySelector(); + + /** + * 比较两个被合成的对象,选择其中的一个并返回 + * + * @param 复合注解类型 + * @param prev 上一对象,该参数不允许为空 + * @param next 下一对象,该参数不允许为空 + * @return 对象 + */ + T choose(T prev, T next); + + /** + * 返回距离根对象更近的注解,当距离一样时优先返回旧注解 + */ + class NearestAndOldestPrioritySelector implements Selector { + @Override + public T choose(T oldAnnotation, T newAnnotation) { + return newAnnotation.getVerticalDistance() < oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation; + } + } + + /** + * 返回距离根对象更近的注解,当距离一样时优先返回新注解 + */ + class NearestAndNewestPrioritySelector implements Selector { + @Override + public T choose(T oldAnnotation, T newAnnotation) { + return newAnnotation.getVerticalDistance() <= oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation; + } + } + + /** + * 返回距离根对象更远的注解,当距离一样时优先返回旧注解 + */ + class FarthestAndOldestPrioritySelector implements Selector { + @Override + public T choose(T oldAnnotation, T newAnnotation) { + return newAnnotation.getVerticalDistance() > oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation; + } + } + + /** + * 返回距离根对象更远的注解,当距离一样时优先返回新注解 + */ + class FarthestAndNewestPrioritySelector implements Selector { + @Override + public T choose(T oldAnnotation, T newAnnotation) { + return newAnnotation.getVerticalDistance() >= oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation; + } + } + + } + +} diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAggregateAnnotation.java b/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAggregateAnnotation.java index fe85356a1..b2d047bb6 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAggregateAnnotation.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAggregateAnnotation.java @@ -34,7 +34,33 @@ import java.util.Collection; * @see SynthesizedAnnotationPostProcessor * @see SynthesizedMetaAggregateAnnotation */ -public interface SynthesizedAggregateAnnotation extends Annotation, AggregateAnnotation { +public interface SynthesizedAggregateAnnotation extends Annotation, AggregateAnnotation, Hierarchical { + + // ================== hierarchical ================== + + /** + * 距离{@link #getRoot()}返回值的垂直距离, + * 默认聚合注解即为根对象,因此返回0 + * + * @return 距离{@link #getRoot()}返回值的水平距离, + */ + @Override + default int getVerticalDistance() { + return 0; + } + + /** + * 距离{@link #getRoot()}返回值的水平距离, + * 默认聚合注解即为根对象,因此返回0 + * + * @return 距离{@link #getRoot()}返回值的水平距离, + */ + @Override + default int getHorizontalDistance() { + return 0; + } + + // ================== synthesize ================== /** * 获取在聚合中存在的指定注解对象 diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotation.java b/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotation.java index 40bd70499..b65370ba2 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotation.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedAnnotation.java @@ -3,7 +3,6 @@ package cn.hutool.core.annotation; import cn.hutool.core.collection.CollUtil; import java.lang.annotation.Annotation; -import java.util.Comparator; import java.util.Map; import java.util.function.UnaryOperator; @@ -16,16 +15,7 @@ import java.util.function.UnaryOperator; * @author huangchengxing * @see SynthesizedAggregateAnnotation */ -public interface SynthesizedAnnotation extends Annotation, Comparable { - - /** - * {@link SynthesizedAnnotation}使用的默认的比较器, - * 按照按{@link #getVerticalDistance()}和{@link #getHorizontalDistance()}的返回值进行排序。
- * 一般情况下,排序越小的合成注解应当被优先处理。 - */ - Comparator DEFAULT_CHILD_PRIORITY_COMPARATOR = Comparator - .comparing(SynthesizedAnnotation::getVerticalDistance) - .thenComparing(SynthesizedAnnotation::getHorizontalDistance); +public interface SynthesizedAnnotation extends Annotation, Hierarchical { /** * 获取所属的合成注解聚合器 @@ -34,13 +24,6 @@ public interface SynthesizedAnnotation extends Annotation, Comparable T choose(T oldAnnotation, T newAnnotation) { - return newAnnotation.getVerticalDistance() < oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation; + return Hierarchical.Selector.NEAREST_AND_OLDEST_PRIORITY.choose(oldAnnotation, newAnnotation); } } @@ -55,7 +55,7 @@ public interface SynthesizedAnnotationSelector { class NearestAndNewestPrioritySelector implements SynthesizedAnnotationSelector { @Override public T choose(T oldAnnotation, T newAnnotation) { - return newAnnotation.getVerticalDistance() <= oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation; + return Hierarchical.Selector.NEAREST_AND_NEWEST_PRIORITY.choose(oldAnnotation, newAnnotation); } } @@ -65,7 +65,7 @@ public interface SynthesizedAnnotationSelector { class FarthestAndOldestPrioritySelector implements SynthesizedAnnotationSelector { @Override public T choose(T oldAnnotation, T newAnnotation) { - return newAnnotation.getVerticalDistance() > oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation; + return Hierarchical.Selector.FARTHEST_AND_OLDEST_PRIORITY.choose(oldAnnotation, newAnnotation); } } @@ -75,7 +75,7 @@ public interface SynthesizedAnnotationSelector { class FarthestAndNewestPrioritySelector implements SynthesizedAnnotationSelector { @Override public T choose(T oldAnnotation, T newAnnotation) { - return newAnnotation.getVerticalDistance() >= oldAnnotation.getVerticalDistance() ? newAnnotation : oldAnnotation; + return Hierarchical.Selector.FARTHEST_AND_NEWEST_PRIORITY.choose(oldAnnotation, newAnnotation); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedMetaAggregateAnnotation.java b/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedMetaAggregateAnnotation.java index 4c9106c46..9a06f37bf 100644 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedMetaAggregateAnnotation.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/SynthesizedMetaAggregateAnnotation.java @@ -52,6 +52,21 @@ public class SynthesizedMetaAggregateAnnotation implements SynthesizedAggregateA */ private final Annotation source; + /** + * 根对象 + */ + private final Object root; + + /** + * 距离根对象的垂直距离 + */ + private final int verticalDistance; + + /** + * 距离根对象的水平距离 + */ + private final int horizontalDistance; + /** * 包含根注解以及其元注解在内的全部注解实例 */ @@ -94,11 +109,35 @@ public class SynthesizedMetaAggregateAnnotation implements SynthesizedAggregateA /** * 基于指定根注解,为其层级结构中的全部注解构造一个合成注解 * - * @param annotation 当前查找的注解对象 - * @param annotationSelector 合成注解选择器 - * @param attributeProcessor 注解属性处理器 + * @param annotation 当前查找的注解对象 + * @param annotationSelector 合成注解选择器 + * @param attributeProcessor 注解属性处理器 + * @param annotationPostProcessors 注解后置处理器 */ public SynthesizedMetaAggregateAnnotation( + Annotation annotation, + SynthesizedAnnotationSelector annotationSelector, + SynthesizedAnnotationAttributeProcessor attributeProcessor, + Collection annotationPostProcessors) { + this( + null, 0, 0, + annotation, annotationSelector, attributeProcessor, annotationPostProcessors + ); + } + + /** + * 基于指定根注解,为其层级结构中的全部注解构造一个合成注解 + * + * @param root 根对象 + * @param verticalDistance 距离根对象的水平距离 + * @param horizontalDistance 距离根对象的垂直距离 + * @param annotation 当前查找的注解对象 + * @param annotationSelector 合成注解选择器 + * @param attributeProcessor 注解属性处理器 + * @param annotationPostProcessors 注解后置处理器 + */ + SynthesizedMetaAggregateAnnotation( + Object root, int verticalDistance, int horizontalDistance, Annotation annotation, SynthesizedAnnotationSelector annotationSelector, SynthesizedAnnotationAttributeProcessor attributeProcessor, @@ -108,6 +147,11 @@ public class SynthesizedMetaAggregateAnnotation implements SynthesizedAggregateA Assert.notNull(attributeProcessor, "attributeProcessor must not null"); Assert.notNull(annotationPostProcessors, "attributePostProcessors must not null"); + // 初始化坐标 + this.root = ObjectUtil.defaultIfNull(root, this); + this.verticalDistance = verticalDistance; + this.horizontalDistance = horizontalDistance; + // 初始化属性 this.source = annotation; this.annotationSelector = annotationSelector; @@ -123,6 +167,36 @@ public class SynthesizedMetaAggregateAnnotation implements SynthesizedAggregateA ); } + /** + * 获取根对象 + * + * @return 根对象 + */ + @Override + public Object getRoot() { + return root; + } + + /** + * 获取与根对象的垂直距离 + * + * @return 与根对象的垂直距离 + */ + @Override + public int getVerticalDistance() { + return verticalDistance; + } + + /** + * 获取与根对象的水平距离 + * + * @return 获取与根对象的水平距离 + */ + @Override + public int getHorizontalDistance() { + return horizontalDistance; + } + /** * 获取根注解 * diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/AliasAnnotationPostProcessorTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/AliasAnnotationPostProcessorTest.java index db9558fd4..922c3cc6b 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/AliasAnnotationPostProcessorTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/AliasAnnotationPostProcessorTest.java @@ -106,6 +106,11 @@ public class AliasAnnotationPostProcessorTest { public Object getAttribute(String attributeName, Class attributeType) { return null; } + + @Override + public Object getRoot() { + return null; + } } static class TestSynthesizedAnnotation implements SynthesizedAnnotation { diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/AliasLinkAnnotationPostProcessorTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/AliasLinkAnnotationPostProcessorTest.java index 1ca645d53..877f8afb2 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/AliasLinkAnnotationPostProcessorTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/AliasLinkAnnotationPostProcessorTest.java @@ -134,6 +134,11 @@ public class AliasLinkAnnotationPostProcessorTest { public Object getAttribute(String attributeName, Class attributeType) { return null; } + + @Override + public Object getRoot() { + return null; + } } static class TestSynthesizedAnnotation implements SynthesizedAnnotation { diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/MirrorLinkAnnotationPostProcessorTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/MirrorLinkAnnotationPostProcessorTest.java index 5f18f9574..d14734229 100644 --- a/hutool-core/src/test/java/cn/hutool/core/annotation/MirrorLinkAnnotationPostProcessorTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/annotation/MirrorLinkAnnotationPostProcessorTest.java @@ -109,6 +109,11 @@ public class MirrorLinkAnnotationPostProcessorTest { return null; } + @Override + public Object getRoot() { + return null; + } + } static class TestSynthesizedAnnotation implements SynthesizedAnnotation {