注解(Annotation)
- 注解就是Java代码中的特殊标记,比如:@Override、@Test等,作用是:让其他程序员根据注解信息来决定怎么执行该程序。
- 注意:注解可以用在类上、构造器上、方法上、成员变量上、参数上、等位置。
自己定义注解
-
特殊属性名:value
- 如果注解中只有一个value属性,value名称可以不写
注解的原理
- 注解本质是一个接口,该接口继承了Annotation接口
- 使用@注解名(....):其实就是一个实现类对象,实现了该注解以及Annotation接口。
元注解
- 修饰注解的注解称为元注解
-
@Target
- 作用:声明被修饰的注解只能在哪些位置使用
-
@Target(ElementType.TYPE,ElementType.FIELD) 1.Type,类,接口 2.FIELD,成员变量 3.METHOD,成员方法 4.PARAMETER,方法参数 5.CONSTRUCTOR,构造器 6.LOCAL_VARIABLE,局部变量
-
@Retention
- 作用:声明注解的保留周期
-
@Retention(RetentionPolicy.RUNTIME) 1.SOURCE,只作用在源码阶段,字节码文件中不存在 2.CLASS(默认值),保留到字节码文件阶段,运行阶段存在 3.RUNTIME(开发常用),一直保留到运行阶段
注解的解析
-
什么是注解解析
- 判断类上、方法上、成员变量上是否存在注解,并把注解里面的内容解析出来
-
如何解析注解
- 核心思想:要解析谁上面的注解,就应该先拿到谁。
- 比如:要解析类上面的注解,则应该先获取该类的Class对象,在通过Class对象解析其上面的注解
- 比如:要解析成员方法上的注解,则应该获取到该成员方法的Method对象,再通过Method对象解析其上面的注解。
- Class、Method、Field、Constructor都实现了AnnotatedElement接口,他们都拥有解析注解的能力
-
AnnotatedElement接口提供解析注解的方法 说明 public Annotation[ ] getDeclaredAnnotations() 获取当前对象上面的注解 public T getDeclaredAnnotation(Class <T> annotationClass) 获取指定注解对象 public boolean isAnnotationPresent(Class <Annotation> annotationClass) 判断当前对象是否存在某个注解
-
案例
- 解析注解的案例,具体要求如下
- 1.定义注解MyTest4,要求如下
- 包含属性:String value()
- 包含属性:double aaa(),默认值为100
- 包含属性:String [ ] bbb()
- 限制注解的使用位置:类和成员变量方法上
- 指定注解的有效范围:一直到运行时
-
package com.example.Anno; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyTest4 { String value(); double aaa() default 100; String[] bbb(); }
-
- 2.定义一个类叫:Demo,在类中定义一个test1方法,并在该类和其方法上使用MyTest4注解
-
package com.example.Test; import com.example.Anno.MyTest4; @MyTest4(value = "蜘蛛精", bbb = {"至尊宝", "紫霞仙子"}, aaa = 99.5) public class Demo { @MyTest4(value = "蜘蛛精1", bbb = {"至尊宝1", "紫霞仙子1"}, aaa = 199.5) public void test1() { } }
-
- 3.定义一个TestAnnotation测试类,解析Demo类中全部注解
-
package com.example.Test; import com.example.Anno.MyTest4; import org.junit.Test; import java.lang.annotation.Annotation; import java.lang.reflect.Method; public class TestAnnotation { @Test public void parseClass() { // 1.先得到Class对象 Class c = Demo.class; // 2.解析类上的注解 // 判断该类上是否包含某个注解 if (c.isAnnotationPresent(MyTest4.class)) { MyTest4 myTest4 = (MyTest4) c.getDeclaredAnnotation(MyTest4.class); System.out.println(myTest4.value()); System.out.println(myTest4.aaa()); System.out.println(myTest4.bbb()); } } @Test public void parseMethod() throws NoSuchMethodException { // 1.先得到Class对象 Class c = Demo.class; Method method = c.getDeclaredMethod("test1"); // 2.解析方法上的注解 // 判断该方法上是否包含某个注解 if (method.isAnnotationPresent(MyTest4.class)) { MyTest4 myTest4 = method.getDeclaredAnnotation(MyTest4.class); System.out.println(myTest4.value()); System.out.println(myTest4.aaa()); System.out.println(myTest4.bbb().toString()); } } }
-
- 1.定义注解MyTest4,要求如下
注解的应用场景
- 配合反射等技术来构建框架
-
案例
- 定义若干个方法,只要加了MyTest注解,就会触发该方法执行
- 分析
- 1.定义一个自定义的注解MyTest,只能注解方法,存活范围是一直都在
-
package com.example.Anno; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; // todo 自定义注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyTest { }
-
- 2.定义若干个方法,部分方法加上@MyTest注解修饰,部分方法不加
- 3.模拟一个Junit程序,可以触发加了@MyTest注解的方法执行
-
package com.example.Test; import com.example.Anno.MyTest; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class TestAnnotation { @MyTest public void test1() { System.out.println("test1---"); } public void test2() { System.out.println("test2---"); } public void test3() { System.out.println("test2---"); } public static void main(String[] args) throws InvocationTargetException, IllegalAccessException { TestAnnotation testAnnotation = new TestAnnotation(); // 启动程序 // 1.得到Class对象 Class c = TestAnnotation.class; // 2.提取类中的全部方法 Method[] declaredMethods = c.getDeclaredMethods(); // 3.遍历数组中的每个方法,然后查看方法是否含有@MyTest注解 for (Method declaredMethod : declaredMethods) { if (declaredMethod.isAnnotationPresent(MyTest.class)) { declaredMethod.invoke(testAnnotation); } } } }
-
- 1.定义一个自定义的注解MyTest,只能注解方法,存活范围是一直都在