1. 注解(Annotation)
- JDK1.5 以后版本引入的一个特性
- 可以被其他程序(比如:编译器)读取
- 语法
@注释名
2. 内置注解
- @Override
- 标记重写父类方法
- @Deprecated
- 标记过时方法,表示不建议再使用
- @SuppressWarnings
- 抑制编译时的警告信息
- 需要添加参数才能正常使用,例如
@SuppressWarnings("unchecked")
3. 元注解(meta-annotation)
- 作用:注解其他注解
- 定义了 4 个标准的 meta-annotation 类型,用来对其他类型作说明
- @Target
- @Retention
- @Documented
- @Inherited
3.1 @Target
- Indicates the contexts in which an annotation type is applicable
public enum ElementType {
TYPE,
FIELD,
METHOD,
PARAMETER,
CONSTRUCTOR,
LOCAL_VARIABLE,
ANNOTATION_TYPE,
PACKAGE,
TYPE_PARAMETER,
TYPE_USE
}
3.2 @Retention
- 描述注解的生命周期
- SOURCE < CLASS < RUNTIME
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
public enum RetentionPolicy {
// 保留在源码阶段,编译时被丢弃
SOURCE,
// 保留到编译进行时的class文件,但 JVM 加载class文件时候被遗弃
CLASS,
// 保留到程序运行时
RUNTIME
}
3.3 @Documented
- 将被记录在 javadoc 中
3.4 @Inherited
- 子类可以继承父类的注解
4. 自定义注解
- 定义注解用 @interface, 注解中只能包含属性
- 里面的方法实际上是声明的属性,方法名称就是属性名称,返回值类型就是属性的类型
- 若只有一个属性,一般名为 value
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EntryLog {
// 属性 value
String value() default "";
String[] codes() default {};
}
若属性没有默认值,必须给注解赋值
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EntryLog {
String value() default "";
String[] codes();
}
// 需给注解赋值
@EntryLog(codes = {"1001", "1002"})
4.1 注解属性类型
- 基本数据类型
- String 类型
- Class 类型
- 枚举类型
- 注解类型
- 以上类型的一维数组
数组用 {} 来存储,当数组中只有一个值时可省略 {}
// 数组类型 String[] codes();
@EntryLog(codes = "1001")
@EntryLog(codes = {"1001", "1002"})
// 枚举数组类型 ElementType[] value();
@Target(ElementType.TYPE)
@Target({ElementType.TYPE, ElementType.METHOD})
4.2 反编译文件
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface EntryLog {
int num() default 0;
String value();
// Class 类型
Class<?> clazz();
// 枚举类型
CodeEnum codeEnum();
// 注解类型
DemoAnno demoAnno();
}
// 自动继承 java.lang.annotation.Annotation 接口
public interface EntryLog extends java.lang.annotation.Annotation {
public abstract int num();
public abstract java.lang.String value();
public abstract java.lang.Class<?> clazz();
public abstract com.example.concrete.CodeEnum codeEnum();
public abstract com.example.concrete.DemoAnno demoAnno();
}
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation> annotationType();
}
5. Spring 注解 @AliasFor
- @AliasFor 用于声明注释属性别名
同一个注解中的两个属性互为别名
例如:@ComponentScan 注解中,value 和 basePackages 两个属性互为别名
public @interface ComponentScan {
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
}
跨注解的属性别名
例如:@Service#value的值可以映射到@Component#value
public @interface Service {
@AliasFor(annotation = Component.class)
String value() default "";
}
public @interface Component {
String value() default "";
}
5.1 @SpringBootApplication 分析
public @interface SpringBootApplication {
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
}
其他
- Java注解是使用动态代理类实现
- 可以通过反射机制实现对元数据的访问
- SpringBoot深入理解 -- @AliasFor注解的作用
网友评论