一、注解 icode9 基础
注解即标注与解析,在Java的 icode9 代码工程中,注解的使用几乎是无处不在,甚至多到被忽视;
无论是在JDK源码或者框架组件,都在使用注解能力完成各种识别和解析动作;在对系统功能封装时,也会依赖注解能力简化各种逻辑的重复实现;
基础接口
在Annotation的源码注释中有说明:所有的注解类型都需要继承该公共接口,本质上看注解是接口,但是代码并没有显式声明继承关系,可以直接查看字节码文件;
-- 1、声明注解
public @interface SystemLog {}
-- 2、查看指令
javap -v SystemLog.class
-- 3、打印结果
Compiled from "SystemLog.java"
public interface com.base.test.SystemLog extends java.lang.annotation.Annotation
元注解
声明注解时使用,用来定义注解的作用目标,保留 icode9 策略等;
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SystemLog { String model () default "" ; }
- Documented:是否被javadoc或类似工具记录在文档中;
- Inherited:标识注解是否可以被子类继承;
- Target:作用目标,在ElementType枚举中可以看到取值包括类、方法、属性等;
- Retention:保留策略,比如编译阶段是否丢弃,运行时保留;
此处声明一个SystemLog注解,作用范围是在方法上,并且在运行时保留,该注解通常用在服务运行时,结合AOP切面编程实现方法的日志采集;
二、注解原理
先来看一个简单的注解使用案例,再细致的分析其中原理,案例并不复杂,就是常见的标注与解析两个关键动作;
public class LogInfo {
@SystemLog(model = "日志模块")
public static void main(String[] args) {
// 生成代理文件
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
// 反射机制
Method[] methods = LogInfo.class.getMethods();
for (Method method:methods){
SystemLog systemLog = method.getAnnotation(SystemLog.class) ;
if (systemLog != null){
// 动态代理:com.sun.proxy.$Proxy2
System.out.println(systemLog.getClass().getName());
System.out.println(systemLog.model());
}
}
}
}
这里涉及到两个核心概念: icode9 反射机制、动态代理;反射机制可以在程序运行时获取类的完整结构信息,代理模式给目标对象提供一个代理对象,由代理对象持有目标对象的引用;
案例中通过反射机制,在程序运行时进行注解的获取和解析,值得关注的是systemLog对象的类名,输出的是代理类信息;
案例执行完毕后,会在代码工程的目录下生成代理类,可以查看$Proxy2
文件;
public final class $Proxy2 extends Proxy implements SystemLog {
public final String model() throws {
try {
return (String)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
}
在对SystemLog解析的过程中,实际上是在使用注解的代理类,$Proxy2
继承了Proxy类并实现了SystemLog接口,并且重写了相关方法;有关反射和代理的逻辑,在之前的内容中有详说,此处不赘述;
值得一看是代理类中invoke方法调用,具体的处理逻辑在AnnotationInvocationHandler类的invoke方法中,会对注解原生方法和自定义方法做判断,并对原生方法提供实现;
三、常用注解
1、JDK注解
在JDK中有多个注解是经常使用的,例如Override、Deprecated、SuppressWarnings等;
- Override:判断方法是否为重写方法;
- Deprecated:标记过时的API,继续使用会警告;
- FunctionalInterface:检验是否为函数式接口;
- SuppressWarnings:代码的警告会静默处理;
这里注意FunctionalInterface注解,从1.8开始引入,检验是否为函数式接口,即接口只能有一个抽象方法,否则编译报错;
2、Lombok注解
在具体的看Lombok组件之前,需要先了解一个概念:代码编译;在open-jdk的描述文档中大致分为三个核心阶段;
第一步:读取命令行上指定的所有源文件,解析为语法树,进行符号表填充;
第二步:调用注解处理器,如果处理器生成任何新的源文件或类文件,编译会重新启动;
本站声明:
1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/293163.html