引言
第一次感受到注解的威力是在使用springboot时,一个注解就能启动一个Web应用,非常厉害,同时又有点神秘
添加一些三方组件时,例如eureka,只需要添加一个注解,加几行配置就能启动一个Eureka Server,客户端也是,添加一个注解就能注册上去(后面不知道哪个版本之后连注解都不需要加了,这里暂不讨论),注解变得愈发神秘
但后面学习注解之后,发现其实注解的知识点并不多也不难,这里记录下相关的笔记吧
作用
个人理解的注解:实际上就是一种加强版的注释,为什么是加强版的呢?因为它能被反射读到,反射的强大,大家应该都有所了解,所以注解本身并没有任何作用,起作用的是反射,注解只是为类,属性,方法等添加一种描述而已
就好比说现在是在战争演习,红蓝双方各自戴着红色及蓝色的帽子,这顶帽子本身无法起到什么作用,不会让你跑的更快,射的更准,它的作用是由你的队友或者对手体现的:
- 队友通过帽子的颜色发现你是自己人,不会误伤你,还会给你发各种信号
- 对手通过帽子的颜色发现你是敌人,上来就是一枪,GG。。
所以帽子本身只是对你身份的另一种描述而已,比如帽子一脱,你该打的还是能打,该开炮的还是能开炮,只是其他人无法通过帽子分辨你是友军还是敌军了而已(少了这个额外的功能),并不会影响你自己的功能
几个小栗子
- 例如Junit,它的规则就是所有加了@Test注解的方法我都会自动执行,这个过程简单说就是下面这样:
1. 测试类启动,通过反射获取所有的方法
2. 遍历方法,通过反射拿到方法注解
3. 是否存在@Test注解?
存在? --- 执行方法
不存在? --- 跳过
- 再例如我们如果想实现
Spring
的AOP
可以怎么做,比如说我们想给所有打了@Log
的方法添加日志(一般会通过切面来做,这里我们假设注解都是自己手动打在方法上的),那我们要做的事情实际上就是两件
1. 找到每个Bean中包含@Log注解的方法
2. 使用动态代理(这里我们假设使用的是JDK动态代理),生成一个代理类Proxy,然后把原来的类强转成这个代理类,为啥可以强转?因为
至于如何让每个Bean都走我这个方法?可以了解下BeanPostProcessor
这个接口,实现这个接口,每个Bean都会走你的实现类
- 再例如我们想实现一个简单的SpringMVC怎么做,这里就留给大家自己思考吧?核心就是将请求的url和类及方法联系起来
使用
定义注解
定义注解主要就是三个方面:
- 适用类型(可以定义在哪些地方)
- 存活策略(一般都是RUNTIME)
- 注解的各种属性
- 属性可以设置默认值
- 所有基本类型(int、float、boolean等)
- String
- Class
- enum
- Annotation
- 以上类型的数组
整个简单的,我想定义一个自己的RequestMapping注解,value是url,方法类型是method(默认值给成"GET")
@Target(value = {ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyRequestMapping {
String value();
String method() default "GET";
}
完成,就是这么简单
使用注解
像字段属性一样赋值,像调用方法一样拿值
// @MyRequestMapping("/test")
@MyRequestMapping(value = "/test",method = "POST")
public class AnnoTest {
public static void main(String[] args) {
MyRequestMapping annotation = AnnoTest.class.getAnnotation(MyRequestMapping.class);
if(annotation != null) {
System.out.println(annotation.value());
System.out.println(annotation.method());
}
}
}
完成,还是这么简单
使用注解的小提示
如果存在value属性,并且只想给value这一个属性赋值的话,那么可以省略属性名,因为默认就是给value属性赋值的。
比如说可以把上面这个例子中的@MyRequestMapping(value = "/test",method = "POST")
替换成@MyRequestMapping("/test")
,看看打印结果