Java自定义注解
Posted 梦Dreamer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java自定义注解相关的知识,希望对你有一定的参考价值。
简介:
注解是在JDK5.0及以后版本中引入的。他可以用于创建文档,跟踪代码中的依赖性,甚至执行基本的编译时检查,而且还可以作为在spring框架中进行注解式注入Bean属性,用来减少写配置文件。注解是以@+注解名在代码中存在的,根据注解参数的个数,我们可以将注解分为:标记注解,单值注解、完整注解三类。他们都不会直接影响到程序的语义,只是作为注解存在,可以通过反射机制编程实现对这些元数据的访问。
java自定义注解的更多介绍,大家可以看下面的系列文章《深入理解Java:注解(Annotation)基本概念》
注解的3中基本类型
a、标记注解 --没有变量,只有名称标示 例如:@annotation
b、单一值注解 --在标记注解的基础上提供一段数据。 例如:@annotation("data")
c、完整注解 --可以包括多个数据成员,每个数据成员由名称和值构成
例如:@annotation(val1="data1",val2="data2")
DEMO
自定义注解的接口声明
package com.ymhj.yas.yoshinoya.aop;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*
* 常用注解说明:
* 1. RetentionPolicy(保留策略)是一个enum类型,有三个值
* SOURCE -- 这个Annotation类型的信息只会保留在程序源码里,源码如果经过了编译后,Annotation的数据就会消失,并不会保留在编译好的.class文件里
* CLASS -- 这个Annotation类型的信息保留在程序源码中,同时也会保留在编译好的.class文件里面,在执行的时候,并不会把这一些信息加载到虚拟 机(JVM)中去.注意一下,当你没有设定一个Annotation类型的Retention值时,系统默认值是CLASS。
* RUNTIME -- 在源码、编译好的.class文件中保留信息,在执行的时候会把这一些信息加载到JVM中去的。
*
* 2.ElementType @Target中的ElementType用来指定Annotation类型可以用在哪些元素上
* TYPE(类型) -- 在Class,Interface,Enum和Annotation类型上
* FIELD -- 属性上
* METHOD -- 方法上
* PARAMETER -- 参数上
* CONSTRUCTOR -- 构造函数上
* LOCAL_VARIABLE -- 局部变量
* ANNOTATION_TYPE -- Annotation类型上
* PACKAGE -- 包上
*
* 3.Documented -- 让这个Annotation类型的信息能够显示在API说明文档上;没有添加的话,使用javadoc生成的API文件找不到这个类型生成的信息
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation
String descraption() default "";
自定义注解的实现
package com.ymhj.yas.yoshinoya.aop;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Order(1) //Spring 4.2 利用@Order控制配置类的加载顺序
public class AnnotationImplement
//切面
@Pointcut("@annotation(com.ymhj.yas.yoshinoya.aop.MyAnnotation)")
public void annotation()
//此处什么都不用写
//此处写具体的实现
//定义通知(前置)
//切面类(依然放在com.abc.advice包中)中定义了Before、Around、AfterReturning和After 4中增强处理
//ProceedingJoinPoint :使用这个类取处理日志,只能处理环绕通知,该类是JoinPoint的子类:ProceedingJoinPoint is only supported for around advice
@Before("annotation()")
public void beforePoint(JoinPoint point)
/**********************注解处理器**************/
System.err.println(point.getTarget().getClass().getName());//获取目标对象对应的类名
//获取实现类继承的接口名
@SuppressWarnings("rawtypes")
Class[] c = point.getTarget().getClass().getInterfaces();
System.err.println("实现类继承的接口名:"+c[0]);
//获取在这个service实现类上的annotation
Annotation[] a = point.getTarget().getClass().getAnnotations();
//获取这个类上的注解的个数
System.out.println("应用注解类上的注解个数:"+a.length);
//判断这个类上面的注释是否是AnnotationName这个自定义的注解,如果是返回这个注解,如果不是返回null
if(point.getTarget().getClass().getAnnotation(MyAnnotation.class)!=null)
//获取到这个类上的注解
MyAnnotation anns = point.getTarget().getClass().getAnnotation(MyAnnotation.class);
//输出这个类上的注解的值
System.out.println("注释在实现类上的annotation:"+anns.descraption());
//判断这个接口上是否存在此注解
if(c[0].getAnnotation(MyAnnotation.class)!=null)
MyAnnotation an = (MyAnnotation) c[0].getAnnotation(MyAnnotation.class);
System.out.println("注解对象所实现接口上的注解值:"+an.descraption());
//获取目标对象上正在执行的方法名
System.err.println("目标对象上正在执行的方法名:"+point.getSignature().getName());//方法名
//获取到这个类上面的所有方法全名
Method meths[] = point.getSignature().getDeclaringType().getMethods();
System.out.println("方法上面的全名:"+meths[0]);
//获取到这个类上面的方法上面的注解
Annotation[] anns = meths[1].getDeclaredAnnotations();
System.out.println("正在执行方法上面的注解:"+((MyAnnotation)anns[2]).descraption());
//让你注释的那个方法执行
//point.proceed();
/**********************注解处理器**************/
Object[] objects=point.getArgs();//参数名
for (int i = 0; i < objects.length; i++)
System.err.println(objects.toString());
上面的demo中,声明的是一个运行时方法注解,所以在使用的时候,可以将@MyAnnotation注解放到某个方法上。
以上是关于Java自定义注解的主要内容,如果未能解决你的问题,请参考以下文章