复合注解的解析

 
/**
 * 复合注解, 注解上面的注解,并且演示怎么进行解析。
 */
public class AnnoTwo {
	
	/**
	 *  基本的注解
	 */
	@Target({ElementType.TYPE,ElementType.METHOD})
	@Retention(RetentionPolicy.RUNTIME)
	@interface Base{
		public String value() default "";
	}
	
	
	/**复合注解,被基本的注解。**/
	@Target(ElementType.METHOD)
	@Retention(RetentionPolicy.RUNTIME)
	@Base("haha")
	@interface Two{
		
	}
	
	/**复合注解的具体使用*/
	@Two
	private String getAll(){
		return "ok";
	}
	
	/**
	 * 复合注解的解析
	 */
	@Test
	public void test1() throws NoSuchMethodException, SecurityException{
		Class<AnnoTwo> x = AnnoTwo.class;
		Method methd = x.getDeclaredMethod("getAll", new Class[]{});
		Annotation[] anns = methd.getDeclaredAnnotations(); /**声明的注解*/
		Annotation a = null;
		for (Annotation ann : anns) {
			if (ann.annotationType() == Base.class) {
				a = ann;
				break;
			}
		}
		if(a==null){
			for (Annotation ann : anns) { /**演示只有2层的,多层需要递归处理*/
				if (ann.annotationType()!= null && !ann.annotationType().getName().startsWith("java.lang.annotation")) {
					Class<? extends Annotation> annParent = ann.annotationType();
					Annotation[]  anns2 = annParent.getDeclaredAnnotations();
					for (Annotation ann2 : anns2) {
						if (ann2.annotationType() == Base.class) {
							a = ann2;
							break;
						}
					}
				}
			}
		}
		if(a==null){
			System.out.println("没找到注解");
		}else{
			Base res = (Base)a;
			System.out.println(res.value());
		}
	}
	
	/**
	 * springUitls的findAnnotation可以解析注解上面的非lang包下的自定义组合注解(即元注解)
	 */
	@Test
	public void test2() throws NoSuchMethodException, SecurityException{
		Class<AnnoTwo> x = AnnoTwo.class;
		Method methd = x.getDeclaredMethod("getAll", new Class[]{});
		Set<Annotation> visited = new HashSet();
		Base base1 = findAnnotation((AnnotatedElement)methd,Base.class, new HashSet());
		Base base2 = AnnotationUtils.findAnnotation(methd, Base.class); //可以得到注解上面的注解,没有返回null
		System.out.println(base1.value());
		System.out.println(base2.value());
	}
	
	/**
	 * 演示spring的实现 (省略类查询过程 )
	 * @param annotatedElement (class method 等等都实现了这个接口,并且Annotation的jvm实现类也实现此接口)
	 * @param annotationType 需要查询的注解类型
	 * @param visited 递归性能优化用
	 */
	private static <A extends Annotation> A findAnnotation(
			AnnotatedElement annotatedElement, Class<A> annotationType, Set<Annotation> visited) {
		try {
			Annotation[] anns = annotatedElement.getDeclaredAnnotations();
			for (Annotation ann : anns) {
				if (ann.annotationType() == annotationType) {
					return (A) ann;
				}
			}
			for (Annotation ann : anns) {
				if (ann!=null && ann.annotationType() != null && !ann.annotationType().getName().startsWith("java.lang.annotation") && visited.add(ann)) { //  visited性能优化用。
					A annotation = findAnnotation((AnnotatedElement) ann.annotationType(), annotationType, visited);
					if (annotation != null) {
						return annotation;
					}
				}
			}
		}
		catch (Throwable ex) {
			return null;
		}
		return null;
	} 
	
}

以上案例:Base base = AnnotationUtils.findAnnotation(methd, Base.class); 可直接获得注解的注解(复合注解!)。没有返回null

posted on 2020-06-01 14:35  芝麻开花——节节高  阅读(583)  评论(0编辑  收藏  举报

导航