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
์ด ๋จผ์ ์ถ๋ ฅ๋์์ต๋๋ค.