梦想还是要有的,万一忘了咋办?

0%

Java注解

背景

今天用idea学习lombok时遇到一个问题,注解@Getter @Setter 编译通过通过struct视图也可以看到动态添加的 方法,但是运行时就会提示方法不存在。开始以为是依赖引入时机不对,调整后还是没有效果。百度一下需要这么操作:
idea设置AnnotationProcessors
此图为gradle依赖
lombok依赖
作为常年使用eclipse的我觉得有必要搞搞清楚idea的这个AnnotionProcessor是个什么鬼东西了。

注解

注解脑图
(此图来自互联网)

AnnotionProcessor

首先并不是idea创造的东西,而是java提供的编译时注解处理机制。两种编译时解析方案
1. APT(Annotation Processing Tool)
2. Pluggable Annotation Processing API

APT

apt自JDK5产生,JDK7已标记为过期、不推荐使用,JDK8中已彻底删除,自JDK6开始,可以使用Pluggable Annotation Processing API来替换它,apt被替换主要有2点原因:

  1. api都在com.sun.mirror非标准包下
  2. 没有集成到javac中,需要额外运行
    apt的更多介绍可以参见这里

Pluggable Annotation Processing API

JSR 269,自JDK6加入,作为apt的替代方案,它解决了apt的两个问题,javac在执行的时候会调用实现了该API的程序,这样我们就可以对编译器做一些增强,这时javac执行的过程如下:
upload successful

做一个AnnotationProcessor

环境

* Mac(gradle)
* IntelliJ IDEA
* Java1.8

* 构建工具Gradle 语言 Groovy

创建项目

upload successful
upload successful
upload successful
upload successful
upload successful

模块author-processorx

upload successful
upload successful
upload successful
upload successful

创建Annotation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.hardydou.learn.annotation.processor;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface EnableAuthor {
String name() default "authorXXX";
String email() default "author@XX.com";
}

创建Processor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.hardydou.learn.annotation.processor;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import java.util.Set;

@SupportedAnnotationTypes({"com.hardydou.learn.annotation.processor.EnableAuthor"})
public class AuthorProcessor extends AbstractProcessor {
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(EnableAuthor.class);

for (Element ele : elements) {
if (ele.getKind() == ElementKind.CLASS) {
EnableAuthor author = ele.getAnnotation(EnableAuthor.class);
System.out.println(ele + "[{author:" + author.name() + "email:" + author.email() + "}");
}
}
return true;
}
}


注册Processor服务

upload successful

模块test

upload successful
upload successful

修改build.gradle文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
plugins {
id 'java'
id 'application'
}

group 'com.hardydou.learn'
version '1.0-SNAPSHOT'
mainClassName = "com.hardydou.learn.annotation.TestProcessor"
sourceCompatibility = 1.8

repositories {
mavenCentral()
}

dependencies {
compile project(":author-processor")
annotationProcessor project(":author-processor")
testCompile group: 'junit', name: 'junit', version: '4.12'
}

创建测试类

1
2
3
4
5
6
7
8
9
10
11
12
package com.hardydou.learn.annotation;

import com.hardydou.learn.annotation.processor.EnableAuthor;

@EnableAuthor(name = "hardy", email = "hardydou@163.com")
public class TestProcessor {

public static void main(String[] args) {
System.out.println("TestProcessor.main");
}
}

执行测试

由于事件发生在编译时,所以每次要执行clean 才可以看到效果
upload successful
upload successful
执行结果
upload successful