반응형
Annotation Processor
설명
- 컴파일 시점에 Annotation 기반으로 코드를 변경하거나 생성하는 방법을 말한다.
- lombok이 Annotation Processor로 만들어졌다.
- 아래 예제는 Student 클래스를 베이스로 StudentWithGetter 클래스를 만드는 예제
- 다중 모듈 방식으로 프로젝트를 구성한다.
annotation-processor-example 모듈
설명
- 최상위 모듈
- plugin 모듈과 application 모듈 관계 설정을 위해 필요
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>annotation-processor-example</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>plugin</module>
<module>application</module>
</modules>
</project>
plugin 모듈
설명
- Annotation Processor 로직을 갖는 모듈
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>11</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
<executions>
<execution>
<id>default-compile</id>
<configuration>
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</execution>
<execution>
<id>compile-project</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Getter
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Getter {
}
GetterProcessor
@SupportedAnnotationTypes("org.example.plugin.getter.Getter")
public class GetterProcessor extends AbstractProcessor {
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) {
for (TypeElement annotation : annotations) {
Element type = roundEnvironment.getElementsAnnotatedWith(annotation).stream().findFirst().orElseGet(null);
String classFullName = type.toString();
String packageName = classFullName.substring(0, classFullName.lastIndexOf("."));
String className = classFullName.substring(packageName.length() + 1);
String newClassName = className + "WithGetter";
StringBuilder code = new StringBuilder();
code.append("package ").append(packageName).append(";\n\n");
code.append("public class ").append(newClassName).append(" {\n");
type.getEnclosedElements().stream()
.filter(e -> e.getKind() == ElementKind.FIELD)
.forEach(field -> {
code.append(" ");
Optional<Modifier> modifier = field.getModifiers().stream().findFirst();
if (modifier.isPresent()) {
code.append(modifier.get().toString().toLowerCase()).append(" ");
}
code.append(field.asType().toString()).append(" ").append(field.toString()).append(";\n\n");
code.append(" ").append("public ").append(field.asType().toString()).append(" ").append(field.toString()).append("() {\n");
code.append(" ").append("return ").append(field.toString()).append(";\n");
code.append(" }\n");
});
code.append("}\n");
try {
JavaFileObject builderFile = processingEnv.getFiler().createSourceFile(packageName + "." + newClassName);
try (PrintWriter out = new PrintWriter(builderFile.openWriter())) {
out.println(code);
}
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
}
javax.annotation.processing.Processor
- Processor 목록을 명시하는 파일
- 패키지명을 포함한 클래스명을 작성한다.
- Processor가 여러개일 경우 개행으로 구분하여 나열할 수 있다.
- 경로 : plugin/src/main/resources/META-INF/services/javax.annotation.processing.Processor
org.example.plugin.getter.GetterProcessor
application 모듈
설명
- Annotation Processor 기능을 활용하는 모듈
- Student 클래스를 두고 컴파일시 Processor를 통해 StudentWithGetter 클래스를 만들어 사용한다.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>application</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>11</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<!-- Annotation Processor 모듈 의존성 추가 -->
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>plugin</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
Student
@Getter
public class Student {
private String name;
private int age;
}
StudentWithGetter
- 컴파일한 후 target/classes 디렉토리 하위에 StudentWithGetter.class 파일이 생성되었는지 확인한다.
public class StudentWithGetter {
private String name;
private int age;
public StudentWithGetter() {
}
public String name() {
return this.name;
}
public int age() {
return this.age;
}
}
Application
public class Application {
public static void main(String[] args) {
StudentWithGetter student = new StudentWithGetter();
student.name();
}
}
참고
반응형
'Development > Java' 카테고리의 다른 글
[Java] Date (0) | 2021.07.24 |
---|---|
[Java] CompletableFuture (0) | 2021.03.30 |
[Java] Reflection (0) | 2021.03.03 |
[Java] Simple Machine Learning (0) | 2021.02.27 |
[Java] Regular Expression (0) | 2020.12.28 |