애노테이션 프로세서

이연중·2021년 1월 25일
1

JAVA

목록 보기
7/20

롬복(Lombok)

  • 표준적으로 작성해야 할 코드를 개발자 대신 생성해주는 라이브러리
  • @Getter, @Setter, @Builder 등

롬복 사용하기

  1. 의존성 추가
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.8</version>
    <scope>provided</scope>
</dependency>
  1. IntelliJ lombok 플러그인 설치
  2. IntelliJ Annotation Processing 옵션 활성화

롬복 동작 원리

  • 컴파일 시점에 애노테이션 프로세서를 사용해 소스코드의 AST(Abstraction Syntax Tree)를 조작

논란

  • 원래는 애노테이션이 붙어있는 클래스의 정보를 참조만 할 수 있고, 수정을 할 수는 없다

  • 공개된 API가 아닌 컴파일러 내부 클래스를 사용하여 기존의 소스 코드를 조작한다

  • 특히 이클립스의 경우엔 Java Agent를 사용하면 컴파일러 클래스까지 조작하여 사용한다

    마찬가지로 공개된 API가 아니기떄문에 버전 호환성에 문제가 생길 수 있다

  • 그럼에도 불구하고 엄청난 편리한 때문에 널리 쓰이고 있으며, 대안이 몇가지 있지만 롬복의 모든 기능과 편의성을 대체하지는 못한다

애노테이션 프로세서

Processor 인터페이스

  • 여러 라운드에 걸쳐 소스 및 컴파일 된 코드를 처리할 수 있음

유틸리티

  • AutoService: 서비스 프로바이더 레지스트리 생성기.
<dependency>
  <groupId>com.google.auto.service</groupId>
  <artifactId>auto-service</artifactId>
  <version>1.0-rc6</version>
</dependency>
@AutoService(Processor.class)
public class MagicMojaProcessor extends AbstractProcessor {
...
}
  • 컴파일 시에 애노테이션 프로세서를 사용하여 META-INF/services/javax.annotation.processor.Processor 파일을 자동으로 생성해 줌

Filer 인터페이스

  • 소스 코드, 클래스 코드 및 리소스를 생성할 수 있는 인터페이스
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Magic.class);
    for (Element element : elements) {
        Name elementName = element.getSimpleName();
        if (element.getKind() != ElementKind.INTERFACE) {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Magic annotation can not be used on " + elementName);
        } else {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Processing " + elementName);
        }

        TypeElement typeElement = (TypeElement)element;
        ClassName className = ClassName.get(typeElement);
		//메서드 생성
        MethodSpec pullOut = MethodSpec.methodBuilder("pullOut")
                .addModifiers(Modifier.PUBLIC)
                .returns(String.class)
                .addStatement("return $S", "Rabbit!")
                .build();
		//클래스 생성
        TypeSpec magicMoja = TypeSpec.classBuilder("MagicMoja")
                .addModifiers(Modifier.PUBLIC)
                .addSuperinterface(className)
                .addMethod(pullOut)
                .build();
		//소스 파일 생성, 바이트 코드 생성
        Filer filer = processingEnv.getFiler();
        try {
            JavaFile.builder(className.packageName(), magicMoja)
                    .build()
                    .writeTo(filer);
        } catch (IOException e) {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "FATAL ERROR: " + e);
        }
    }
    return true;
}

유틸리티

  • Javapoet: 소스 코드 생성 유틸리티

애노테이션 프로세서 정리

애노테이션 프로세서 사용 예

애노테이션 프로세서 장점

  • 런타임 비용이 없음(컴파일 타임에 조작이 완료된 상황이기때문에)

참고

https://www.inflearn.com/course/the-java-code-manipulation

profile
Always's Archives

0개의 댓글