参考资料
如何定义一个注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface MyAnnotation {
String title() default "";
String[] urls() default "";
boolean isTrue() default true;
}
获取注解
反射
前提条件
只有 RetentionPolicy.RUNTIME 的注解可以被反射获取。
@Target(ElementType.TYPE)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Ann1 {
}
@Ann1
public class Ann1Client {
public static void main(String[] args) {
Annotation[] annotations = Ann1Client.class.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}
ElementType.TYPE_PARAMETER
@Target(value = {
ElementType.TYPE_PARAMETER
})
@Retention(RetentionPolicy.RUNTIME)
@interface Ann7 {
String value();
}
@Target(value = {
ElementType.TYPE_USE
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann8 {
String value();
}
public class UseAnn100<@Ann7("this is A") @Ann8("this is AA") A,
@Ann7("this is B") @Ann8("this is BB") B,
@Ann7("this is C") @Ann8("this is CC") C> {
public static void main(String[] args) {
TypeVariable<Class<UseAnn100>>[] typeParameters = UseAnn100.class.getTypeParameters();
for (TypeVariable<Class<UseAnn100>> typeParameter : typeParameters) {
Annotation[] annotations = typeParameter.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}
}
ElementType.PACKAGE
@Target(value = {
ElementType.PACKAGE
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann9 {
String value();
}
@Ann9("this is type package")
package com.example.lurenjia.spring.c16;
public class PackageInfoMain {
public static void main(String[] args) {
Package p = Package.getPackage("com.example.lurenjia.spring.c16");
Annotation[] annotations = p.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}
ElementType.METHOD
@Target(value = {
ElementType.METHOD
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann101 {
String value();
}
public class UseAnn101 {
@Ann101("a")
public void a() {
}
public static void main(String[] args) {
Method[] declaredMethods = UseAnn101.class.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
Annotation[] annotations = declaredMethod.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}
}
ElementType.CONSTRUCTOR
@Target(value = {
ElementType.CONSTRUCTOR
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann102 {
String value();
}
public class UseAnn102 {
@Ann102(value = "const")
public UseAnn102() {
}
public static void main(String[] args) {
Constructor<?>[] declaredConstructors = UseAnn102.class.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
Annotation[] declaredAnnotations = declaredConstructor.getDeclaredAnnotations();
for (Annotation declaredAnnotation : declaredAnnotations) {
System.out.println(declaredAnnotation);
}
}
}
}
ElementType.PARAMETER
@Target(value = {
ElementType.PARAMETER
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann103 {
String value();
}
public class UseAnn103 {
public void a(@Ann103("a") int a, @Ann103("b") int b) {
}
public static void main(String[] args) {
Method[] declaredMethods = UseAnn103.class.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
Parameter[] parameters = declaredMethod.getParameters();
for (Parameter parameter : parameters) {
Annotation[] annotations = parameter.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}
}
}
ElementType.FIELD
@Target(value = {
ElementType.FIELD
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann104 {
String value();
}
public class UseAnn104 {
@Ann104("a . ")
int a;
@Ann104("b . ")
int b;
public static void main(String[] args) {
Field[] fields = UseAnn104.class.getDeclaredFields();
for (Field field : fields) {
Annotation[] annotations = field.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}
}
ElementType.LOCAL_VARIABLE
@Target(value = {
ElementType.LOCAL_VARIABLE
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann105 {
String value();
}
public class UseAnn105 {
public UseAnn105() {
}
public void a(int a, int b) {
}
}
由于在 jdk8的class文件也就是字节码中不保留局部变量上的注解信息,所以 ElementType.LOCAL_VARIABLE 暂时没有实际效果。
ElementType.ANNOTATION_TYPE
@Target(value = {
ElementType.ANNOTATION_TYPE
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann106 {
String value();
}
@Target(value = {
ElementType.FIELD
})
@Ann106("Ann106")
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann104 {
String value();
}
public class UseAnn106 {
public static void main(String[] args) {
Annotation[] annotations = Ann105.class.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}
ElementType.TYPE_USE
可以当任何类型来使用
@Target({ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@interface Ann10 {
String value();
}
Aop
@Aspect
@Component
public class MyAnnotationAop {
private final static Logger logger = LoggerFactory.getLogger(MyAnnotationAop.class);
@Pointcut("@annotation(com.example.micannotation.annotation.MyAnnotation)")
public void MyAnnotationPointcut() {
}
/**
* 方式一
* @param joinPoint
*/
@Before("MyAnnotationPointcut()")
public void before(JoinPoint joinPoint) {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
String title = annotation.title();
logger.info(" 1 title = {}", title);
Object[] args = joinPoint.getArgs();
logger.info(Arrays.toString(args));
}
/**
* 方式二
* @param joinPoint
* @param annotation
*/
@Before("@annotation(annotation)")
public void before(JoinPoint joinPoint, MyAnnotation annotation) {
String title = annotation.title();
logger.info(" 2 title = {}", title);
Object[] args = joinPoint.getArgs();
logger.info(Arrays.toString(args));
}
}
常见的注解
内置注解
@SuppressWarnings 消除警告
@Override 重写方法
@Deprecated 过时方法,不推荐使用
元注解
修饰注解的注解
指定注解的使用范围:@Target
ElementType[] value();
public enum ElementType {
/*类、接口、枚举、注解上面*/
TYPE,
/*字段上*/
FIELD,
/*方法上*/
METHOD,
/*方法的参数上*/
PARAMETER,
/*构造函数上*/
CONSTRUCTOR,
/*本地变量上*/
LOCAL_VARIABLE,
/*注解上*/
ANNOTATION_TYPE,
/*包上*/
PACKAGE,
/*类型参数上*/
TYPE_PARAMETER,
/*类型名称上*/
TYPE_USE
}
注解的作用对象
指定注解的保留策略:@Retention
public @interface Retention {
RetentionPolicy value();
}
public enum RetentionPolicy {
编译后丢弃,也就是java文件生效
SOURCE,
class文件生效,jvm运行时丢失
CLASS,
jvm运行时仍然存在
RUNTIME
}
@Documented
@Inherit:实现类之间的注解继承
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Ann21 {
}
@Ann21
public class UseAnn21 {
}
@Ann21
public interface UseAnn21_ {
}
public class UseAnn21Son extends UseAnn21 {
public static void main(String[] args) {
Annotation[] annotations = UseAnn21Son.class.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}
public class UseAnn21Son_ implements UseAnn21_{
public static void main(String[] args) {
Annotation[] annotations = UseAnn21Son_.class.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
}
}
@com.example.lurenjia.spring.c16.Ann21()
注意,接口的实现类不会继承接口上被 @Inherit 修饰的注解
@Repeatable重复使用注解
如果我们尝试重复使用一个注解,默认下会提示如下的错误。
不使用 @Repeatable 怎么实现 ?
@MyAnnotations(array = {@MyAnnotation(title = "is title"), @MyAnnotation(title = "is title2")})
---
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Documented
public @interface MyAnnotations {
MyAnnotation[] array();
}
使用 @Repeatable
需要定义两个注解,一个容器注解和一个原始注解。
@Target(value = {
ElementType.TYPE_USE
})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Ann110s.class)
public @interface Ann110 {
}
@Target(value = {
ElementType.TYPE_USE
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann110s {
Ann110[] value();
}
使用 @Repeatable 后多了一种使用方法
@Ann110("1")
@Ann110("2")
@Ann110("3")
@Ann110("4")
public class UseAnn110s {
public static void main(String[] args) {
}
}