目录
1:什么是注解
注解是annotation,注解不会影响代码的执行,可以给代码(方法、类、属性字段)打上标签,来定义代码的一些特征。
使用注解,可以减少配置文件,简化代码(我们传统中的spring配置通过注解大量减少配置),比如我们给类贴上@service @controller的注解。spring容器会把这些类变成bean加入工厂管理。
注解就是标签,给代码加上描述。
2:举例说明怎么使用注解(分析java的一些注解)
1:@Test(作用在方法)
2:@service @controller(作用在类)
我们怎么知道的?看源码
//test注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD}) //METHOD作用在方法
public @interface Test {
}
//Controller注解
@Target({ElementType.TYPE})//作用到类
@Retention(RetentionPolicy.RUNTIME)//运行时也会生效
@Documented//生成文档描述
@Component//这里是核心 Controller的注解实际上就是作用在类上的Component注解
public @interface Controller {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
@AliasFor(annotation = Component.class)
String value() default "";
}
3:使用自定义注解
3.1:注解元标签
我们知道注解就是标签,那么标签上我们要写什么呢?就像一张便利贴,贴到一个物品的上边,我们写什么呢?写的东西就是元标签,元标签有5个,我们可以选择的来用。
首先了解元注解,元注解就是标签上的固定行,可以选择一些,但是一定要有。
元标签有5个:
@Retention、(编译范围 是关键)
@Documented、(生成文档 可选)
@Target、(目标选择 类、字段、方法 是关键)
@Inherited、(继承关系 可选)
@Repeatable (可复用 可选)
@Retention(注解运行范围的三个枚举值选择)
RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。
@Documented
顾名思义,这个元注解肯定是和文档有关。它的作用是能够将注解中的元素包含到 Javadoc 中去。
@Target
Target 是目标的意思,@Target 指定了注解运用的地方。
你可以这样理解,当一个注解被 @Target 注解时,这个注解就被限定了运用的场景。
类比到标签,原本标签是你想张贴到哪个地方就到哪个地方,但是因为 @Target 的存在,它张贴的地方就非常具体了,比如只能张贴到方法上、类上、方法参数上等等。@Target 有下面的取值
ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
ElementType.CONSTRUCTOR 可以给构造方法进行注解
ElementType.FIELD 可以给属性进行注解
ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
ElementType.METHOD 可以给方法进行注解
ElementType.PACKAGE 可以给一个包进行注解
ElementType.PARAMETER 可以给一个方法内的参数进行注解
ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
@Inherited
Inherited 是继承的意思,但是它并不是说注解本身可以继承,而是说如果一个超类被 @Inherited 注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。
@Repeatable
Repeatable 自然是可重复的意思。@Repeatable 是 Java 1.8 才加进来的,所以算是一个新的特性。
什么样的注解会多次应用呢?通常是注解的值可以同时取多个。
3.2:注解自定义(注解就是接口前边加@)
//注解1:接口前边加@ 就是注解(想那里贴就往哪里贴)
@Retention(RetentionPolicy.RUNTIME) //RUNTIME就是在运行时也会生效 class编译的时候存在
@Documented //标签写入javaDoc文档
@Target({ElementType.TYPE, ElementType.METHOD}) //标签贴的位置 type给类注解 METHOD方法注解 可以多个
@Inherited //@Inherited 修饰,之后类 A 被 Test 注解,类 B 继承 A,类 B 也拥有 Test 这个注解。
//@Repeatable(TestAnnotation1.class)
public @interface TestAnnotation {
//相当定义了变量 方法名字=变量名 返回值=变量类型 (int id=null)
int id();
//相当定义了变量 方法名字=变量名 返回值=变量类型 String name="李四";
String name() default "李四";
}
//注解2:接口前边加@ 就是注解(向往那里贴就往哪里贴)
@Retention(RetentionPolicy.RUNTIME) //RUNTIME标签的存活时间 class编译的时候存在
@Documented //标签写入javaDoc文档
@Target({ElementType.TYPE, ElementType.METHOD,ElementType.FIELD}) //标签贴的位置 type给类注解 METHOD方法注解 可以多个
@Inherited //@Inherited 修饰,之后类 A 被 Test 注解,类 B 继承 A,类 B 也拥有 Test 这个注解。
//@Repeatable(TestAnnotation1.class)
public @interface TestAnnotation1 {
//相当定义了变量 方法名字=变量名 返回值=变量类型 (int id=null)
String value() ;
}
//过期方法注解测试
public class User1 {
@Deprecated
public void add(){
System.out.println("过期方法");
}
public void add1(){
System.out.println("不是过期方法");
}
}
测试代码测试注解:
@TestAnnotation(id = 3, name = "你好 张三!") //类时候用注解 有两个属性
public class Test1 {
@TestAnnotation1(value = "测试变量注解的值")//属性使用注解1 只有一个属性
String value;
/**
* 基础注解案例
*/
@Test
@TestAnnotation(id = 4) //方法使用注解
//@SuppressWarnings("deprecation")//加入注解 会不在警告
public void add() {
User1 user1 = new User1();
user1.add();
user1.add1();
System.out.println("测试方法1");
}
/**
* 方法 使用注解获取值
*/
@Test
public void add1() {
//是否使用了指定的注解类
boolean b = Test1.class.isAnnotationPresent(TestAnnotation.class);
System.out.println("Test1是否注解:" + b);
if (b) {
//获取使用的指定注解
TestAnnotation testAnnotation = Test1.class.getAnnotation(TestAnnotation.class);
System.out.println("获取注解的id:" + testAnnotation.id());
System.out.println("获取注解的名字:" + testAnnotation.name());
}
}
/**
* 变量注解 使用注解获取值
*/
@Test
public void add2() throws NoSuchFieldException {
//反射获取变量
Field b = Test1.class.getDeclaredField("value");
b.setAccessible(true);
System.out.println(b.getName());//输出变量
TestAnnotation1 testAnnotation1 = b.getAnnotation(TestAnnotation1.class);
System.out.println("获取变量值:" + testAnnotation1.value());
}
/**
* 方法 使用注解获取值
*/
@Test
public void add3() throws NoSuchFieldException, NoSuchMethodException {
//反射获取方法
Method method = Test1.class.getDeclaredMethod("a");
Annotation[] nnotations = method.getAnnotations();
for (Annotation annotation : nnotations) {
System.out.println("得到的注解:" + annotation);
if (annotation instanceof TestAnnotation1) {
System.out.println("111:" + ((TestAnnotation1) annotation).value());
}
}
}
}