Annotation

  • Java 5๋ถ€ํ„ฐ ๋“ฑ์žฅํ•œ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.
  • ํ”ํžˆ ์•Œ๊ณ  ์žˆ๋Š” @Override, @Deprecated์ด ๋Œ€ํ‘œ์ ์ธ ์˜ˆ์ž…๋‹ˆ๋‹ค.
  • AOP(Aspect Oriented Programing; ๊ด€์‹ฌ์ง€ํ–ฅํ”„๋กœ๊ทธ๋ž˜๋ฐ)์„ ํŽธ๋ฆฌํ•˜๊ฒŒ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Annotation์˜ ํŠน์ง•์€ ๋ญ˜๊นŒ?

  • ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ์ฝ”๋“œ ๋ฌธ๋ฒ• ์—๋Ÿฌ๋ฅผ ์ฒดํฌํ•˜๋„๋ก ์ •๋ณด๋ฅผ ์ œ๊ณต
  • ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ ํˆด์ด ๋นŒ๋“œ๋‚˜ ๋ฐฐ์น˜ ์‹œ ์ฝ”๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ์ •๋ณด๋ฅผ ์ œ๊ณต
  • ์–ด๋…ธํ…Œ์ด์…˜์„ ๋งŒ๋“ค ๋•Œ ์šฉ๋„๋ฅผ ๋ถ„๋ช…ํ•˜๊ฒŒ ํ•ด์•ผ ํ•œ๋‹ค.
    • ์†Œ์Šค์ƒ์—์„œ๋งŒ ์œ ์ง€ํ•ด์•ผ ํ• ์ง€
    • ์ปดํŒŒ์ผ๋œ ํด๋ž˜์Šค์—๋„ ์œ ์ง€ํ•ด์•ผ ํ• ์ง€
    • ๋Ÿฐํƒ€์ž„ ์‹œ์—๋„ ์œ ์ง€ํ•ด์•ผ ํ• ์ง€๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค.

Built-in Annotation

@Override

  • ๋ฉ”์†Œ๋“œ๊ฐ€ ์˜ค๋ฒ„๋ผ์ด๋“œ ๋๋Š”์ง€ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
  • ๋งŒ์•ฝ ๋ถ€๋ชจ ํด๋ž˜์Šค ๋˜๋Š” ๊ตฌํ˜„ํ•ด์•ผํ•  ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค๋ฉด ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ๋‚ฉ๋‹ˆ๋‹ค.

@Deprecated

  • ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ง๋„๋ก ์œ ๋„ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์ปดํŒŒ์ผ ๊ฒฝ๊ณ ๋ฅผ ์ผ์œผํ‚ต๋‹ˆ๋‹ค.

@SuppressWarnings

  • ์ปดํŒŒ์ผ ๊ฒฝ๊ณ ๋ฅผ ๋ฌด์‹œํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

@SafeVarargs

  • ์ œ๋„ˆ๋ฆญ ๊ฐ™์€ ๊ฐ€๋ณ€์ธ์ž ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๊ฒฝ๊ณ ๋ฅผ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. (์ž๋ฐ”7 ์ด์ƒ)

@FunctionalInterface

  • ๋žŒ๋‹ค ํ•จ์ˆ˜๋“ฑ์„ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”์†Œ๋“œ๊ฐ€ ์—†๊ฑฐ๋‚˜ ๋‘๊ฐœ ์ด์ƒ ๋˜๋ฉด ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ๋‚ฉ๋‹ˆ๋‹ค. (์ž๋ฐ” 8์ด์ƒ)

Meta Annotations

Meta Annotation์„ ํ™œ์šฉํ•ด Custom Annotation์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@Retention

  • ์–ด๋…ธํ…Œ์ด์…˜์˜ Life Time์ž…๋‹ˆ๋‹ค.
  • Class
    • ๋ฐ”์ดํŠธ ์ฝ”๋“œ ํŒŒ์ผ๊นŒ์ง€ ์–ด๋…ธํ…Œ์ด์…˜ ์ •๋ณด๋ฅผ ์œ ์ง€ํ•œ๋‹ค.
    • ํ•˜์ง€๋งŒ ๋ฆฌํ”Œ๋ ‰์…˜์„ ์ด์šฉํ•ด์„œ ์–ด๋…ธํ…Œ์ด์…˜ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜๋Š” ์—†๋‹ค.
  • Runtime
    • ๋ฐ”์ดํŠธ ์ฝ”๋“œ ํŒŒ์ผ๊นŒ์ง€ ์–ด๋…ธํ…Œ์ด์…˜ ์ •๋ณด๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ๋ฆฌํ”Œ๋ ‰์…˜์„ ์ด์šฉํ•ด์„œ ๋Ÿฐํƒ€์ž„์‹œ์— ์–ด๋…ธํ…Œ์ด์…˜ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.
  • Source
    • Compile ์ดํ›„๋กœ ์‚ญ์ œ๋˜๋Š” ํ˜•ํƒœ
  • https://docs.oracle.com/javase/8/docs/api/java/lang/annotation/RetentionPolicy.html

@Documented

  • ๋ฌธ์„œ์—๋„ ์–ด๋…ธํ…Œ์ด์…˜์˜ ์ •๋ณด๊ฐ€ ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค.

@Target

  • ์ ์šฉํ•  ์œ„์น˜๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

@Inherited

  • ์ž์‹ํด๋ž˜์Šค๊ฐ€ ์–ด๋…ธํ…Œ์ด์…˜์„ ์ƒ์† ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@Repeatable

  • ๋ฐ˜๋ณต์ ์œผ๋กœ ์–ด๋…ธํ…Œ์ด์…˜์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

Annotation ๊ตฌ์กฐ

@Inherited // ์ƒ์†
@Documented // ๋ฌธ์„œ์— ์ •๋ณด๊ฐ€ ํ‘œํ˜„
@Retention(RetentionPolicy.RUNTIME) // ์ปดํŒŒ์ผ ์ดํ›„์—๋„ JVM์— ์˜ํ•ด์„œ ์ฐธ์กฐ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค
@Retention(RetentionPolicy.CLASS)   // Compiler๊ฐ€ ํด๋ž˜์Šค๋ฅผ ์ฐธ์กฐํ•  ๋•Œ๊นŒ์ง€ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค
@Retention(RetentionPolicy.SOURCE)  // ์ปดํŒŒ์ผ ์ดํ›„ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค
@Target({
		ElementType.PACKAGE, // ํŒจํ‚ค์ง€ ์„ ์–ธ์‹œ
		ElementType.TYPE, // ํƒ€์ž… ์„ ์–ธ์‹œ
		ElementType.CONSTRUCTOR, // ์ƒ์„ฑ์ž ์„ ์–ธ์‹œ
		ElementType.FIELD, // ๋ฉค๋ฒ„ ๋ณ€์ˆ˜ ์„ ์–ธ์‹œ
		ElementType.METHOD, // ๋ฉ”์†Œ๋“œ ์„ ์–ธ์‹œ
		ElementType.ANNOTATION_TYPE, // ์–ด๋…ธํ…Œ์ด์…˜ ํƒ€์ž… ์„ ์–ธ์‹œ
		ElementType.LOCAL_VARIABLE, // ์ง€์—ญ ๋ณ€์ˆ˜ ์„ ์–ธ์‹œ
		ElementType.PARAMETER, // ๋งค๊ฐœ ๋ณ€์ˆ˜ ์„ ์–ธ์‹œ
		ElementType.TYPE_PARAMETER, // ๋งค๊ฐœ ๋ณ€์ˆ˜ ํƒ€์ž… ์„ ์–ธ์‹œ
		ElementType.TYPE_USE // ํƒ€์ž… ์‚ฌ์šฉ์‹œ
})
public @interface NesoyAnnotation{
	/* enum ํƒ€์ž…์„ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. */
	public enum Quality {
		BAD, GOOD, VERYGOOD
	}
 
	/* String์€ ๊ธฐ๋ณธ ์ž๋ฃŒํ˜•์€ ์•„๋‹ˆ์ง€๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. */
	String value() default "NesoyAnnotation : Default String Value";
 
	/* ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. */
	int[] values();
 
	/* enum ํ˜•ํƒœ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. */
	Quality quality() default Quality.GOOD;
}

Custom Annotation ๋งŒ๋“ค์–ด๋ณด๊ธฐ

Nesoy Annotation

  • Annotation์€ RUNTIME์— ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ์ ์šฉํ•  ๋ฒ”์œ„๋Š” Method๋งŒ ์ž…๋‹ˆ๋‹ค.
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME) // ์ปดํŒŒ์ผ ์ดํ›„์—๋„ JVM์— ์˜ํ•ด์„œ ์ฐธ์กฐ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค
@Target({
		ElementType.METHOD, // ๋ฉ”์†Œ๋“œ ์„ ์–ธ์‹œ
})
public @interface NesoyAnnotation{
	String value() default "NesoyAnnotation : Default String Value"; // ๊ธฐ๋ณธ ๊ฐ’์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
}

Nesoy Object

  • ํ‰์†Œ Annotation์„ ์‚ฌ์šฉํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
class NesoyObject{
	@NesoyAnnotation(value = "I'm Annotation") // ์ƒˆ๋กœ์šด value๋ฅผ ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
	public void annotationTest(){
		System.out.println("Hello! Nesoy");
	}
}

ContextContainer

  • Java์˜ Reflection์„ ํ™œ์šฉํ•ด์„œ Object์˜ Annotation invoke๋Š” ์—ญํ• ์ž…๋‹ˆ๋‹ค.
  • Java์˜ Reflection์„ ํ™œ์šฉํ•ด์„œ Annotation์˜ value๋ฅผ ์ฝ์–ด๋“ค์ด๋Š” ์—ญํ• ์ž…๋‹ˆ๋‹ค.
class MyContextContainer {
	public MyContextContainer(){}
	/**
	 * ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์ „ ์–ด๋…ธํ…Œ์ด์…˜์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
	 * @param instance
	 * @param <T>
	 * @return
	 * @throws IllegalAccessException
	 */
	private <T> T invokeAnnonations(T instance) throws IllegalAccessException {
		Method[] methods = instance.getClass().getDeclaredMethods(); // Reflect์œผ๋กœ ํ•ด๋‹น ํด๋ž˜์Šค์˜ Method๋ฅผ ์ „๋ถ€ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.
 
		for(Method method : methods){
			NesoyAnnotation annotation = method.getAnnotation(NesoyAnnotation.class); // Method๋“ค ์ค‘์— NesoyAnnotation์„ ์ฐพ์Šต๋‹ˆ๋‹ค.
			if(annotation != null) { // NesoyAnnotation์ด ์กด์žฌํ•œ๋‹ค๋ฉด
				System.out.println(annotation.value()); // annotation์˜ value๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.
			}
		}
 
		return instance;
	}
 
	/**
	 * ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์€ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
	 * @param clazz
	 * @param <T>
	 * @return
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	public <T> T get(Class clazz) throws IllegalAccessException, InstantiationException {
		T instance = (T) clazz.newInstance();
		instance = invokeAnnonations(instance);
		return instance;
	}
}

Main

public class Main {
	public static void main(String[] args) throws InstantiationException, IllegalAccessException {
		MyContextContainer demo = new MyContextContainer(); // Annotation์„ ํ˜ธ์ถœํ•  Container๋ฅผ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.
		NesoyObject object = demo.get(NesoyObject.class); // Container์—์„œ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ ธ์˜ค๋ฉด์„œ Annotation์„ invokeํ•ฉ๋‹ˆ๋‹ค.
		object.annotationTest(); // Method๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.
	}
}

๊ฒฐ๊ณผ๋ฌผ

  • ๊ธฐ์กด์˜ Method์—๋Š” "Hello! Nesoy"๋งŒ ์žˆ์—ˆ์ง€๋งŒ Annotation์œผ๋กœ ์ธํ•ด I'm Annotation์ด ๋จผ์ € ์ถœ๋ ฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Reference