mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
!654 新增注解扫描器和合成注解
Merge pull request !654 from Createsequence/feat-synthetic-annotation
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
package cn.hutool.core.annotation;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 合成注解{@link SyntheticAnnotation}的测试用例
|
||||
*
|
||||
* @author huangchengxing
|
||||
*/
|
||||
public class SyntheticAnnotationTest {
|
||||
|
||||
@Test
|
||||
public void testSynthesisAnnotation() {
|
||||
ChildAnnotation rootAnnotation = AnnotatedClass.class.getAnnotation(ChildAnnotation.class);
|
||||
SyntheticAnnotation<ChildAnnotation> syntheticAnnotation = SyntheticAnnotation.of(rootAnnotation);
|
||||
Assert.assertEquals(syntheticAnnotation.getSource(), rootAnnotation);
|
||||
Assert.assertEquals(syntheticAnnotation.annotationType(), rootAnnotation.annotationType());
|
||||
Assert.assertEquals(1, syntheticAnnotation.getDeclaredAnnotations().length);
|
||||
Assert.assertEquals(syntheticAnnotation.getDeclaredAnnotations()[0], rootAnnotation);
|
||||
Assert.assertEquals(3, syntheticAnnotation.getAnnotations().length);
|
||||
|
||||
Assert.assertEquals(syntheticAnnotation.getAttribute("childValue", String.class), "Child!");
|
||||
Assert.assertEquals(syntheticAnnotation.getAttribute("childValueAlias", String.class), "Child!");
|
||||
Assert.assertEquals(syntheticAnnotation.getAttribute("parentValue", String.class), "Child's Parent!");
|
||||
Assert.assertEquals(syntheticAnnotation.getAttribute("grandParentValue", String.class), "Child's GrandParent!");
|
||||
|
||||
Map<Class<? extends Annotation>, SyntheticAnnotation.MetaAnnotation> annotationMap = syntheticAnnotation.getMetaAnnotationMap();
|
||||
ChildAnnotation childAnnotation = syntheticAnnotation.getAnnotation(ChildAnnotation.class);
|
||||
Assert.assertTrue(syntheticAnnotation.isAnnotationPresent(ChildAnnotation.class));
|
||||
Assert.assertNotNull(childAnnotation);
|
||||
Assert.assertEquals(childAnnotation.childValue(), "Child!");
|
||||
Assert.assertEquals(childAnnotation.childValueAlias(), "Child!");
|
||||
Assert.assertEquals(childAnnotation.grandParentType(), Integer.class);
|
||||
Assert.assertEquals(annotationMap, SyntheticAnnotation.of(childAnnotation).getMetaAnnotationMap());
|
||||
|
||||
ParentAnnotation parentAnnotation = syntheticAnnotation.getAnnotation(ParentAnnotation.class);
|
||||
Assert.assertTrue(syntheticAnnotation.isAnnotationPresent(ParentAnnotation.class));
|
||||
Assert.assertNotNull(parentAnnotation);
|
||||
Assert.assertEquals(parentAnnotation.parentValue(), "Child's Parent!");
|
||||
Assert.assertEquals(parentAnnotation.grandParentType(), "java.lang.Void");
|
||||
Assert.assertEquals(annotationMap, SyntheticAnnotation.of(parentAnnotation).getMetaAnnotationMap());
|
||||
|
||||
GrandParentAnnotation grandParentAnnotation = syntheticAnnotation.getAnnotation(GrandParentAnnotation.class);
|
||||
Assert.assertTrue(syntheticAnnotation.isAnnotationPresent(GrandParentAnnotation.class));
|
||||
Assert.assertNotNull(grandParentAnnotation);
|
||||
Assert.assertEquals(grandParentAnnotation.grandParentValue(), "Child's GrandParent!");
|
||||
Assert.assertEquals(grandParentAnnotation.grandParentType(), Integer.class);
|
||||
Assert.assertEquals(annotationMap, SyntheticAnnotation.of(grandParentAnnotation).getMetaAnnotationMap());
|
||||
}
|
||||
|
||||
// 注解结构如下:
|
||||
// AnnotatedClass -> @ChildAnnotation -> @ParentAnnotation -> @GrandParentAnnotation
|
||||
// -> @GrandParentAnnotation
|
||||
@ChildAnnotation(childValueAlias = "Child!", grandParentType = Integer.class)
|
||||
static class AnnotatedClass {}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.ANNOTATION_TYPE })
|
||||
@interface GrandParentAnnotation {
|
||||
String grandParentValue() default "";
|
||||
Class<?> grandParentType() default Void.class;
|
||||
}
|
||||
|
||||
@GrandParentAnnotation(grandParentValue = "Parent's GrandParent!") // 覆盖元注解@GrandParentAnnotation的属性
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE })
|
||||
@interface ParentAnnotation {
|
||||
String parentValue() default "";
|
||||
String grandParentType() default "java.lang.Void";
|
||||
}
|
||||
|
||||
@GrandParentAnnotation(grandParentValue = "Child's GrandParent!") // 重复的元注解,靠近根注解的优先级高
|
||||
@ParentAnnotation(parentValue = "Child's Parent!") // 覆盖元注解@ParentAnnotation的属性
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
@interface ChildAnnotation {
|
||||
String childValueAlias() default "";
|
||||
@Alias("childValueAlias")
|
||||
String childValue() default "";
|
||||
Class<?> grandParentType() default Void.class;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
package cn.hutool.core.annotation.scanner;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author huangchengxing
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
|
||||
@interface AnnotationForScannerTest {
|
||||
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package cn.hutool.core.annotation.scanner;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author huangchengxing
|
||||
*/
|
||||
public class FieldAnnotationScannerTest {
|
||||
|
||||
@Test
|
||||
public void testFieldAnnotationScanner() {
|
||||
FieldAnnotationScanner scanner = new FieldAnnotationScanner();
|
||||
Field field = ReflectUtil.getField(Example.class, "id");
|
||||
Assert.assertNotNull(field);
|
||||
Assert.assertTrue(scanner.support(field));
|
||||
List<Annotation> annotations = scanner.getAnnotations(field);
|
||||
Assert.assertEquals(1, annotations.size());
|
||||
Assert.assertEquals(AnnotationForScannerTest.class, CollUtil.getFirst(annotations).annotationType());
|
||||
}
|
||||
|
||||
public static class Example {
|
||||
@AnnotationForScannerTest
|
||||
private Integer id;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
package cn.hutool.core.annotation.scanner;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author huangchengxing
|
||||
* @date 2022/06/10 16:51
|
||||
*/
|
||||
public class MateAnnotationScannerTest {
|
||||
|
||||
@Test
|
||||
public void testMateAnnotationScanner() {
|
||||
AnnotationScanner scanner = new MateAnnotationScanner();
|
||||
Assert.assertTrue(scanner.support(AnnotationForScannerTest3.class));
|
||||
Map<Class<? extends Annotation>, Annotation> annotations = CollUtil.toMap(scanner.getAnnotations(AnnotationForScannerTest3.class), new HashMap<>(), Annotation::annotationType);
|
||||
Assert.assertEquals(3, annotations.size());
|
||||
Assert.assertTrue(annotations.containsKey(AnnotationForScannerTest.class));
|
||||
Assert.assertTrue(annotations.containsKey(AnnotationForScannerTest1.class));
|
||||
Assert.assertTrue(annotations.containsKey(AnnotationForScannerTest2.class));
|
||||
Assert.assertFalse(annotations.containsKey(AnnotationForScannerTest3.class));
|
||||
|
||||
scanner = new MateAnnotationScanner(false);
|
||||
Assert.assertTrue(scanner.support(AnnotationForScannerTest3.class));
|
||||
annotations = CollUtil.toMap(scanner.getAnnotations(AnnotationForScannerTest3.class), new HashMap<>(), Annotation::annotationType);
|
||||
Assert.assertEquals(1, annotations.size());
|
||||
Assert.assertTrue(annotations.containsKey(AnnotationForScannerTest2.class));
|
||||
Assert.assertFalse(annotations.containsKey(AnnotationForScannerTest.class));
|
||||
Assert.assertFalse(annotations.containsKey(AnnotationForScannerTest1.class));
|
||||
Assert.assertFalse(annotations.containsKey(AnnotationForScannerTest3.class));
|
||||
}
|
||||
|
||||
@AnnotationForScannerTest3
|
||||
static class Example {}
|
||||
|
||||
@AnnotationForScannerTest
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
|
||||
@interface AnnotationForScannerTest1 {}
|
||||
|
||||
@AnnotationForScannerTest1
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
|
||||
@interface AnnotationForScannerTest2 {}
|
||||
|
||||
@AnnotationForScannerTest2
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
|
||||
@interface AnnotationForScannerTest3 {}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package cn.hutool.core.annotation.scanner;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author huangchengxing
|
||||
*/
|
||||
public class MethodAnnotationScannerTest {
|
||||
|
||||
@Test
|
||||
public void testMethodAnnotationScanner() {
|
||||
AnnotationScanner scanner = new MethodAnnotationScanner();
|
||||
Method method = ReflectUtil.getMethod(Example.class, "test");
|
||||
Assert.assertNotNull(method);
|
||||
Assert.assertTrue(scanner.support(method));
|
||||
List<Annotation> annotations = scanner.getAnnotations(method);
|
||||
Assert.assertEquals(1, annotations.size());
|
||||
Assert.assertEquals(CollUtil.getFirst(annotations).annotationType(), AnnotationForScannerTest.class);
|
||||
}
|
||||
|
||||
static class Example {
|
||||
@AnnotationForScannerTest
|
||||
public void test() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
package cn.hutool.core.annotation.scanner;
|
||||
|
||||
import cn.hutool.core.util.ClassUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author huangchengxing
|
||||
* @date 2022/06/10 16:51
|
||||
*/
|
||||
public class TypeAnnotationScannerTest {
|
||||
|
||||
@Test
|
||||
public void testTypeAnnotationScanner() {
|
||||
AnnotationScanner scanner = new TypeAnnotationScanner();
|
||||
Assert.assertTrue(scanner.support(Example.class));
|
||||
List<Annotation> annotations = scanner.getAnnotations(Example.class);
|
||||
Assert.assertEquals(3, annotations.size());
|
||||
annotations.forEach(a -> Assert.assertEquals(a.annotationType(), AnnotationForScannerTest.class));
|
||||
|
||||
// 不查找父接口
|
||||
scanner = new TypeAnnotationScanner().setIncludeInterfaces(false);
|
||||
Assert.assertTrue(scanner.support(Example.class));
|
||||
annotations = scanner.getAnnotations(Example.class);
|
||||
Assert.assertEquals(2, annotations.size());
|
||||
annotations.forEach(a -> Assert.assertEquals(a.annotationType(), AnnotationForScannerTest.class));
|
||||
|
||||
// 不查找父类
|
||||
scanner = new TypeAnnotationScanner().setIncludeSupperClass(false);
|
||||
Assert.assertTrue(scanner.support(Example.class));
|
||||
annotations = scanner.getAnnotations(Example.class);
|
||||
Assert.assertEquals(1, annotations.size());
|
||||
annotations.forEach(a -> Assert.assertEquals(a.annotationType(), AnnotationForScannerTest.class));
|
||||
|
||||
// 不查找ExampleSupplerClass.class
|
||||
scanner = new TypeAnnotationScanner().addExcludeTypes(ExampleSupplerClass.class);
|
||||
Assert.assertTrue(scanner.support(Example.class));
|
||||
annotations = scanner.getAnnotations(Example.class);
|
||||
Assert.assertEquals(1, annotations.size());
|
||||
annotations.forEach(a -> Assert.assertEquals(a.annotationType(), AnnotationForScannerTest.class));
|
||||
|
||||
// 只查找ExampleSupplerClass.class
|
||||
scanner = new TypeAnnotationScanner().setFilter(t -> ClassUtil.isAssignable(ExampleSupplerClass.class, t));
|
||||
Assert.assertTrue(scanner.support(Example.class));
|
||||
annotations = scanner.getAnnotations(Example.class);
|
||||
Assert.assertEquals(2, annotations.size());
|
||||
annotations.forEach(a -> Assert.assertEquals(a.annotationType(), AnnotationForScannerTest.class));
|
||||
}
|
||||
|
||||
@AnnotationForScannerTest
|
||||
static class ExampleSupplerClass implements ExampleInterface {}
|
||||
|
||||
@AnnotationForScannerTest
|
||||
interface ExampleInterface {}
|
||||
|
||||
@AnnotationForScannerTest
|
||||
static class Example extends ExampleSupplerClass {}
|
||||
|
||||
}
|
Reference in New Issue
Block a user