注解是干什么的
注解本身不提供作用,注解只能是被看作元数据,它不包含任何业务逻辑。注解更像是一个标签,一个声明,表面被注释的这个地方,将具有某种特定的逻辑。
注解常见的种类
常见的注解有三大类:JDK的,自定义的,第三方的(比如框架)
注解三板斧
定义、使用、读取
定义:包括名字,能用到哪些地方,有效期,是否可以被继承
使用:定义好之后在允许的地方使用标注即可
光有前两步,没什么用,如最熟悉的@Override注解,为什么能验证重写是否有效,怎么不是验证重载?spring的@Autowired为什么是注入作用,而不是输出一句话?显然,他们在程序中做了实现,使得其注解具有各自的作用,也具有了意义,而赋予灵魂的一步就是读取
读取:让注解发挥作用,给注解注入灵魂
注解前置知识
首先是元注解,Java中提供了四个
@Documented | @Retention | @Target | @Inherited
分别解释下
@Documented
代表着此注解会被javadoc工具提取成文档
@Retention:
代表该注解的有效期
SOURCE 表示编译期,如@Override,只做编译时的提示,不会写入字节码中。
CLASS表示类加载期,会保存在class文件中,但在运行class文件被丢弃,也是默认值
RUNTIME 表示运行期,也是最常用的,可以在代码运行时进行反射执行相关的操作
@Target:
表示这个注解可以放在哪
TYPE:接口、类、枚举、注解
FIELD:字段、枚举的常量
METHOD:方法
PARAMETER:参数
CONSTRUCTOR:构造函数
LOCAL_VARIABLE:局部变量
ANNOTATION_TYPE:注解
PACKAGE:包
@Inherited:
表示子类可以继承该类的注解
举个例子
自己自定义个注解,并赋予它作用,模拟aop功能,在方法前后加入
定义注解
1 2 3 4 5 6 7 8 9 10 11 12
| @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyBefore {}
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyCore {}
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyAfter {}
|
使用注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Test { @MyBefore public void init() { System.out.println("初始化"); } @MyAfter public void destroy() { System.out.println("销毁"); } @MyCore public void core() { System.out.println("核心方法"); } }
|
前两步简单,重要的是如何赋予注解作用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| public class MyWork { public static void main(String[] args) throws Exception{ Class clazz = Test.class; Object obj = clazz.newInstance(); List<Method> myBeforeList = new ArrayList<>(); List<Method> myAfterList = new ArrayList<>(); List<Method> myTestList = new ArrayList<>(); Method[] methods = clazz.getMethods(); for (Method method : methods) { if (method.isAnnotationPresent(MyBefore.class)) { myBeforeList.add(method); continue; } if (method.isAnnotationPresent(MyCore.class)) { myTestList.add(method); continue; } if (method.isAnnotationPresent(MyAfter.class)) { myAfterList.add(method); continue; } } for (Method test : myTestList) { for (Method method : myBeforeList) { method.invoke(obj); } test.invoke(obj); for (Method method : myAfterList) { method.invoke(obj); } } } }
|
输出
初始化
核心方法
销毁