JAVA 注解

一、注解是什么?

官方概念:java支持在源文件中嵌入补充信息,这类信息被称为注解,也被称为元数据。
个人理解:注解,就是标记。

二、注解有什么用?

1.用过spring的人我想天天都在用@Controller、@Autowrite、@Service 等等注解,这些注解的作用实际上只是标记而已。
如:框架启动时,main方法中跑一套初始化动作,遍历一遍所有的类,取出带有@Service注解的类,进行实例化,将实例化后的对象装入容器中,再遍历出所有带有@Autowrite注释的属性,将该属性的类型所对应的对象赋值给该属性,这就实现了依赖注入的特性,一切都是反射的功劳。

 

2.还有,很多人都用过一个叫lombok的工具,以@Getter @Setter 注解自动生成getter/setter 方法,这可不是程序能干的活,生成源代码的事情只有编译器才能做,这就是注解的第二种用法,在编译中使用,而不是在运行中使用。

 

三、内置注解

注解接口 应用场合 作用
@Deprecated 全部 将注解内容标记为过时
@Override 方法 方法重写
@Resource 类、接口 标记为要在其他地方要用到的资源
@Resource 属性、方法 注入
@FunctionalInterface 接口 标记为函数式接口
@Target 注解(只能在注解上使用的注解叫做 元注解) 表示该注解可以在哪里使用  详细枚举有点多 不细说 点进源码一目了然
@Retention 注解 保留策略 

 

 

 

 

 

 

 

 

 

保留策略 :3个枚举(SOURCE 、CLASS 、RUNTIME)   SOURCE在编译期间丢弃   CLASS编译时保存在.class文件中 但是会被JVM丢弃   RUNTIME在运行中依旧保留可以被反射机制发现

还有一些@Documented、@Inherited、@PostConstruct、@PreDestroy等等冷门注解,个人认为没必要特别关注。

 

四、注解声明

官方概念分了好几个类型 说的词一套一套的高深莫测,但实际上就下面这几种声明  

public @ interface Controller {
}

//裸注解  直接@Controller使用

 

public @ interface Annot {
    String name();
   int sex() default 1;//默认值 }

//带参数的注解需要传参数  @Annot(name="aaaaa")      @Annot(name="aaaaa",sex="2")

 

public @ interface Mapper {
    String value();//value是特殊名字
}

//之所以value()是特殊名字,是因为它既可以@Mapper(value = "aaaaa") 用 也可以 @Mapper("aaaaa")用

 

以上只是示例声明的写法  而正常的注解都会在头上加两个元注解

@Target(ElementType.METHOD)//只能在方法上应用
@Retention(RetentionPolicy.RUNTIME)//保留策略选择运行中
public @ interface Mapper {
    String value();//value是特殊名字
}

 

五、注解使用(反射使用)

因为注解可以用在类头上,属性头上,方法头上,参数头上,写法都是用反射,非常相似,写出来不免有点多又重复,我自己看的时候也会觉得无趣

所以为避免拉低博客水准,这里只示例两个,全部示例请查看源码分享

 

        try {
            Class cla = Class.forName("TestController");
            if (cla.isAnnotationPresent(Controller.class)) {
                System.out.println("TestController类含有Controller注解");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

 

        try {
            Class cla = Class.forName("TestController");
            Method[] methods = cla.getDeclaredMethods();
            Arrays.stream(methods).forEach((v) -> {
                Parameter[] parameters = v.getParameters();
                Arrays.stream(parameters).filter((a)->a.isAnnotationPresent(Param.class)).forEach((aa)->{
                    Annotation annotation = aa.getAnnotation(Param.class);
                    System.out.println(v.getName() + "方法的" + aa.getName() + "参数有Param注解 值是" + ((Param) annotation).value());
                    //注明一点 aa.getName() 所得到的名称实际上是arg0、arg1一类的 原因是编译器在编译的时候将参数名称替换成了arg+index格式
                });
            });
        } catch (Exception e) {
            e.printStackTrace();
        }

 

 

六、注解使用(编译使用)

研究中 待补充

 

七、源码分享

Fork me on Gitee

 

posted @ 2018-10-22 22:29  不该相遇在秋天  阅读(362)  评论(0编辑  收藏  举报