注解定义
注解(Annotation)又称 Java 标注,是 JDK 5.0 引入的一种注释机制,如果说代码的注释是给程序员看的,那么注解就是给程序看的,程序看到注解后就可以在运行时拿到注解,根据注解来增强运行时的能力。
我们打开 @Deprecated 这个注解看看 @Documented @Retention(RetentionPolicy.RUNTIME) @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE}) public @interface Deprecated { }
注解实现原理
常见的应用在代码中的注解有如下三个:
@Override 检查该方法是否重写了父类方法,如果发现父类或实现的接口中没有此方法,则报编译错误
@Deprecated 标记过时的类,方法,属性等
@SuppressWarnings - 指示编译器去忽略注解中声明的警告。
元注解: @Documented, @Retention, @Target
即注解 Deprecated 或其他自定义注解的注解,其他注解的行为由这些注解来规范和定义,这些元注解的类型及作用如下:
@Documented 表明它会被javadoc(文档注释)之类的工具处理,这样最终注解类型信息也会被包括在生成的API帮助文档中。
@Retention 注解的三种保存策略:
RetentionPolicy.SOURCE
源代码级别的注解,表示指定的注解只在编译期可见,并不会写入字节码文件,Override, SuppressWarnings 就属于此类型,这类注解对于程序员来说主要起到在编译时提醒的作用,在运行保存意义并不大,所以最终并不会被编译入字节码文件中。
RetentionPolicy.RUNTIME
表示注解会被编译入最终的字符码文件中,JVM 启动后也会读入注解,这样我们在运行时就可以通过反射来获取这些注解,根据这些注解来做相关的操作,这是多数自定义注解使用的保存策略。
这里可能大家有个疑问,为啥 Deprecated 被标为 RUNTIME 呢,对于程序员来说,理论上来说只关心调用的类,方法等是否 Deprecated 就够了,运行时获取有啥意义呢,考虑这样一种场景,假设你想在生产上统计过时的方法被调用的频率以评估你工程的坏味道或作为重构参考,此时这个注解是不是派上用场了。
RetentionPolicy.CLASS
注解会被编译入最终的字符码文件,但并不会载入JVM中(在类加载的时候注解会被丢弃),这种保存策略不常用,主要用在字节码文件的处理中。
@Target 表示该注解可以用在什么地方,默认可以用在任何地方,该注解的作用域主要由value来指定,例举常见类型:
FIELD 作用于属性
METHOD 作用于方法
ElementType.TYPE: 作用于类、接口(包括注解类型) 或 enum 声明
@interface
再来看 @interface,反编译之后就会发现在字节码中编译器将其编码成了如下内容。
public interface Override extends Annotation { }
Annotation 是啥:是一个接口!
注解的本质:是继承了 Annotation 这个接口的接口,并且辅以 Retention,Target 这些规范注解运行时行为、作用域等的元注解。
自定义注解的例子(每个格都是一个文件!)
例1:日志脱敏
package com.tools.log;
public enum SensitiveType {ID_CARD, PHONE, NAME, IMG_BASE64} |
package com.tools.log;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Target(value = {ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface SensitiveInfo { SensitiveType type(); } |
package com.tools.log;
public class Request { @SensitiveInfo(type = SensitiveType.NAME) private String name; @SensitiveInfo(type = SensitiveType.ID_CARD) private String idcard; @SensitiveInfo(type = SensitiveType.PHONE) private String phone; @SensitiveInfo(type = SensitiveType.IMG_BASE64) private String imgBase64; } |
例2:支付接口
还没有完成!!!通了,只是逻辑还没理解。
参考:https://mp.weixin.qq.com/s/yNK07ktYhJYLPtTzDBhpww
常用注解:
@Inherited:标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
类继承关系中@Inherited的作用
类继承关系中,子类会继承父类使用的注解中被@Inherited修饰的注解
接口继承关系中@Inherited的作用
接口继承关系中,子接口不会继承父接口中的任何注解,不管父接口中使用的注解有没有被@Inherited修饰
类实现接口关系中@Inherited的作用
类实现接口时不会继承任何接口中定义的注解
链接:https://www.jianshu.com/p/7f54e7250be3
Spring中的注解
@Component
泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
在Annotaion配置注解中用@Component来表示一个通用注释用于说明一个类是一个Spring容器管理的类。即该类已经拉入到Spring的管理中了。
@Controller, @Service, @Repository
是@Component的细化,这三个注解比@Component带有更多的语义,它们分别对应了控制层、服务层、持久层的类。
@Repository
不加这个注解的dao,应该是用了xml进行注入,不然会错
作者:西伯尔
出处:http://www.cnblogs.com/sybil-hxl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。