1일차 어노테이션_자바

nakyeonko3·2024년 2월 19일
0

학습목표

  • 어노테이션을 사용하는 이유 (효과) 는 무엇일까?
  • 나만의 어노테이션은 어떻게 만들 수 있을까?

어노테이션을 사용하는 이유


어노테이션 개념


어노테이션메타데이터의 한 형태이다.
메타 데이터는 또 뭐고, 어노테이션은 무슨 뜻이지?

- 메타 데이터

  • 데이터를 설명해주기 위한 데이터다.
  • 아래 사진에 표에서 처럼 표의 속성을 나타태는 이름('name'), 아이디('id') 같이 표 안의 데이터를 설명하는 데이터가 메타 데이터 이다.
  • 데이터베이스에서는 스키마가 메타데이터라고 할 수 있다.

- 어노테이션

  • 어노테이션은 메타데이터의 한 형태이다.
  • 프로그램에게 어떻게 컴파일하고 실행 할 것 인지에 대한 정보를 준다.
  • 어노테이션 테그가 프로그램에게 이를 해당 소스코드를 런타임에서 어떻게 실행하고, 어떻게 컴파일할지를 설명해주는 셈이다.

  • 주석(Comment)과는 달리 프로그램 실행 방식에 영향을 끼칠 수 있다.

어노테이션의 용도


어노테이션은 다음 세 가지 용도로 사용이 된다.

1) 컴파일러에게 코드 문법 에러를 체크 관련 정보를 제공. ex) @Override
2) 소프트웨어 개발 톨이나 빌드시 코드를 자동으로 생성 할 수 있도록 정보를 제공함. ex) @QueryEntity
2) 런타임 시(실행시) 특정 기능을 실행하도록 정보를 제공 ex) @Scheduled, @Async

- @Override

  • 해당 어노테이션을 메서드 위에 붙이면 메서드가 상위 클래스에 선언된 메서드를 오버라이딩한 메서드라는 것을 컴파일러에게 알려준다.
  • 오버라이딩한 메서드가 상위 메서드와 일치 하지 않을 경우 컴파일러가 경고 메시지를 출력한다.
class Animal {
    public void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Dog barks");
    }
}
class Cat extends Animal {
    @Override
    public void sond() { // "The method sond() of type Cat must override or implement a supertype method"
        System.out.println("Dog barks"); 
    }
}

위의 코드에서는 오버라이딩한 메서드인 sound의 철자가 틀려서 컴파일러가 경고 메시지를 출력한다.

- @Scheduled

이 어노테이션을 메서드 위에 붙이면 해당 메서드가 주기적으로 실행되도록 스케줄링을 통해 동작한다.

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class MyScheduledTask {

    @Scheduled(fixedRate = 5000) // 5초마다 실행
    public void myTask() {
        // 특정 기능 실행
        System.out.println("mytask executed");
    }
}

위 코드를 실행을 하면 5초 마다 mytask executed라는 메시지를 콘솔창에 출력한다.

사용자 정의 어노테이션 만들기


사용자 정의 어노테이션의 구성 요소

사용자 정의 주석의 기본 구조는 다음과 같다.

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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) // Can be changed to TYPE, FIELD, etc., based on where you want to use it
public @interface YourCustomAnnotation {
    // Define annotation elements here
    String value() default "Default Value";
}
  1. @Retention 
    • 어노테이션 유지 정책을 의미한다.
    • 해당 어노테이션이 소스 코드 상에서만 유지 할 것인지, 런타임 시에도 유지 할 것인지, 컴파일 된 클래스까지 유지 할 것인지를 결정함.
    • RetentionPolicy.RUNTIME은 런타임 시점에서도 어노테이션이 유지가 된다.
  2. @Target 
    • 메서드, 클래스, 필드 등 사용자 정의 어노테이션을 적용할 수 있는 위치를 정의함.
    • @Target(ElementType.METHOD)는 메서드에 사용자 정의 어노테이션을 사용한다는 뜻이됨.
  3. element :
    • 어노테이션의 각 엘리먼트는 타입과 이름으로 구성된다.
    • String value() default "Default Value";는 어노테이션의 멤버 변수로 default뒤에 기본값은 "Default Value"이다.

리플렉션

  • 런타임 시에 클래스에 대한 메타 정보를 얻는 기능을 의미함

  • 자바의 리플렉션에서는 런타임 동안에 객체의 클래스 이름, 메서드, 타입 등의 정보를 추출할 수 있다.

  • getMethods()를 통해 해당 클래스의 대한 정보를 가져오고 invoke를 이용해서 해당 메서드를 실행 할 수 도 있음.

  • 주로 테스트나 재컴파일 없이 동적으로 클래스 속성을 바꾸는 용도로 쓰인다.

  • 해당 객체에 대한 메타 정보들(해당 객체의 클래스명, 메서드, 등)을 가져오는 방식으로 테스할 때 쓸 수 있다.

public class TestRunner {
    public void runTest(String className, String methodName) throws Exception {
        Class<?> clazz = Class.forName(className);
        Object instance = clazz.newInstance();
        Method method = clazz.getDeclaredMethod(methodName);
        method.setAccessible(true);
        method.invoke(instance);
    }
}

// Usage
new TestRunner().runTest("com.example.MyTestClass", "testMethod");

사용자 정의 어노테이션 예제

소스 코드 github 링크

package com.practice.annotation.vogella;

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

@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface CanRun {
    String author() default "konakyeon";
    int number() default 5;
}
  • @Target은 메서드에만 적용되도록하고, @Retention은 런타임 시까지 어노테이션 정보를 유지하게 함.
package com.practice.annotation.vogella;

public class AnnotationRunner {

    @CanRun
    public void method1(){
        System.out.println("method1");
    }

    public void method2() {
        System.out.println("method2");
    }
    @CanRun(author = "Minho", number = 10)
    public void method3(){
        System.out.println("method3");
    }
    @CanRun(author = "Zeeto", number = 11)
    public void method5(){
        System.out.println("method4");
    }
}
package com.practice.annotation.vogella;
import java.lang.reflect.Method;

public class MyTest {
    public static void main(String[] args) {
        AnnotationRunner runner = new AnnotationRunner();
        Method [] methods = runner.getClass().getMethods();

        for (Method method : methods) {
            CanRun annos = method.getAnnotation(CanRun.class);
            if(annos != null) {
                try {
                    method.invoke(runner);
                    System.out.println("author:" + annos.author());
                    System.out.println("number" + annos.number()+"\n");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
  • Method [] methods = runner.getClass().getMethods();
    :getClass().getMethods() 통해서 runner객체에 어노테이션이 적용된 메소드들의 정보를 가져와서 methods변수에 저장함.

  • CanRun annos = method.getAnnotation(CanRun.class);
    annos객체에 authornumber 를 가져와서 저장한다.

  • method.invoke(runner);
    runner의 메서드들을 호출시킴. 위 코드를 실행 시켜 보면 method1, method2, method3를 실행 시킨다.

  • System.out.println("author:" + annos.author()); System.out.println("number" + annos.number()+"\n");
    어노테이션 정보를 출력함. 각 메서드에 넣은 authornumber 변수 를 출력함.

실행결과:

method2는 어노테이션을 하지 않았기 때문에 출력되지 않았다.

참고 자료

☕ 자바 제네릭(Generics) 개념 & 문법 정복하기

[Java] 리플렉션 (Reflection)이란 무엇일까? (개념/ 예시)

Java • Beginners Guide To Reflection | KapreSoft

profile
블로그 이전 작업중. 올해(2024년)까지만 여기에 블로그글만 올릴 것임.

0개의 댓글