服务运行时,日志采集结合AOP切面编程实现方式;2.注解原理首先来看一个简单的注解用例,然后详细分析原理。案例并不复杂,就是常见的注解和分析两个关键动作;publicclassLogInfo{@SystemLog(model="logmodule")publicstaticvoidmain(String[]args){//生成代理文件System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");//反射机制Method[]methods=LogInfo.class.getMethods();for(Methodmethod:methods){SystemLogsystemLog=method.getAnnotation(SystemLog.class);if(systemLog!=null){//动态代理:com.sun.proxy.$Proxy2System.out.println(systemLog.getClass().getName());System.out.println(systemLog.model());}}}}有两个核心概念:反射机制,动态代理;反射机制可以在程序运行时获取类的完整结构信息,代理模式为目标对象提供代理对象,代理对象持有目标对象的引用;通过案例中的反射机制,在程序运行时获取并解析注解。值得关注的是systemLog对象的类名,输出的是代理类信息;案例执行后会在代码工程目录下生成代理类,可以查看$Proxy2文件;publicfinalclass$Proxy2extendsProxyimplementsSystemLog{publicfinalStringmodel()throws{try{return(String)super.h.invoke(this,m3,(Object[])null);}catch(RuntimeException|Errorvar2){throwvar2;}catch(Throwablevar3){thrownewUndeclaredThrowableException(var3);}}}在解析SystemLog的过程中,实际使用的是注解的代理类。$Proxy2继承了Proxy类并实现了SystemLog接口,并重写了相关方法;反射和代理的逻辑在前面的内容中已经详细讲过,这里不再赘述;代理类中的invoke方法调用值得一看。具体处理逻辑在AnnotationInvocationHandler类的invoke方法中,会判断注解的native方法和自定义方法,Native方法提供实现;三、常用注解1、JDK注解JDK中有多个注解是经常用到的,比如Override、Deprecated、SuppressWarnings等;override:判断方法是否为重写方法;Deprecated:标记一个过时的API,如果继续使用它会被警告;FunctionalInterface:检查是否为函数式接口;SuppressWarnings:代码的警告会被静默处理;这里注意FunctionalInterface注解,从1.8开始引入,检查是否为函数式接口,即接口只能有一个抽象方法,否则编译错误;2.Lombok注解在详细看Lombok组件之前,需要了解一个概念:代码编译;在open-jdk的描述文档中大致分为三个核心阶段;第一步:读取命令行上指定的所有源文件,解析成语法树,并填充符号表;第二步:调用注解处理器,如果处理器产生任何新的源文件或类文件,编译将重新开始;第三步:解析器对创建的语法树进行解析,转化为class文件;更多细节请参考openjdk文档中Compiler模块的内容,再回到Lombok组件;Lombok组件在代码工程中使用频率很高,注解的方式极其简化JavaBean对象的写法,提高了效率,使源码看起来简洁;这是一个简单的代码来演示其效果。在IdKey类中,使用三个常用的Lombok注解来替代类中很多基本方法的显式生成。检查编译后的文件是否确实有相关方法;@Data@AllArgsConstructor@NoArgsConstructorpublicclassIdKey{privateIntegerid;私人字符串密钥;publicstaticvoidmain(String[]args){IdKeyidKey01=newIdKey(1,"蝉");System.out.println(idKey01);idKey01.setId(2);idKey01.setKey("微笑");System.out.println(idKey01);}}这里需要了解一下JDK中注解处理器的相关源码,AbstractProcessor是作为超类使用的,编译器在编译的时候会检查这个类的子类。子类的核心是process方法;--1.Lombok处理器@SupportedAnnotationTypes("*")publicclassLombokProcessorextendsAbstractProcessor{privateJavacTransformertransformer;@Overridepublicbooleanprocess(Setannotations,RoundEnvironmentroundEnv){transformer.transform(prio,javacProcessingEnv.getContext(),cusForThisRound,清理);}}--2.AST抽象树publicclassJavacTransformer{publicvoidtransform(longpriority,Contextcontext,List
