CORE
HOME > JAVA > J2SE > CORE
2018.09.23 / 16:15

Java¿¡¼­ Ä¿½ºÅÒ ¾î³ëÅ×À̼Ç(Annotation) ¸¸µé°í »ç¿ëÇϱâ

hangawee
Ãßõ ¼ö 197

Ä¿½ºÅÒ ¾î³ëÅ×À̼ÇÀ» ¸¸µé¾î º¸ÀÚ.

Java¿¡¼­ ¾î³ëÅ×À̼Ç(Annotation)À̶õ?
Æ÷½ºÆÿ¡¼­ ¾î³ëÅ×À̼ǿ¡ ´ëÇØ °£´ÜÈ÷ ¾Ë¾Æº¸¾Ò½À´Ï´Ù.

À̹ø Æ÷½ºÆÿ¡¼­´Â Á÷Á¢ Ä¿½ºÅÒ ¾î³ëÅ×À̼ÇÀ» ÀÛ¼ºÇÏ´Â ¹æ¹ý¿¡ ´ëÇÏ¿© ¾Ë¾Æº¸µµ·Ï ÇÏ°Ú½À´Ï´Ù.
µÎ °¡ÁöÀÇ ¿¹Á¦¸¦ ÅëÇØ ¾Ë¾Æº¸µµ·Ï ÇÏ°Ú½À´Ï´Ù.


1. Á¤¼ö °ª ÁÖÀÔ ¿¹Á¦

óÀ½ ÁÖÁ¦´Â ¾î³ëÅ×À̼ÇÀ» ¼±¾ðÇÑ Á¤¼öÇü º¯¼ö¿¡ °ªÀ» ³Ö´Â ¿¹Á¦¸¦ ÁøÇàÇغ¸°Ú½À´Ï´Ù.

°£´ÜÇÑ ¿¹Á¦ À̹ǷΠÁÖ¼®Àº ´ÞÁö ¾Ê°Å³ª °£´ÜÇÑ ¼³¸íÀ¸·Î ´ëüÇÏ°Ú½À´Ï´Ù.

1. ¾î³ëÅ×ÀÌ¼Ç ÀÎÅÍÆäÀ̽º ÀÛ¼º

1
2
3
4
5
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InsertIntData {
int data() default 0;
}

ÀÎÅÍÆäÀ̽º¸¦ ¸¸µé¾îÁִµ¥ ¾Õ¿¡ @ Ç¥½Ã¸¦ ºÙÀÌ¸é µË´Ï´Ù.
1¹ø°ú 2¹ø¿¡ ´ëÇÑ ¼³¸íÀº ¾î³ëÅ×À̼ǠÆ÷½ºÆÿ¡¼­ Á¤¸®ÇÏ¿´½À´Ï´Ù.
ÀÏ´Ü ¸â¹ö º¯¼ö¿¡ data¶ó´Â ÁÖÀÔÀ» ¹ÞÀ» °ªÀ» ¸¸µé¾î ÁÝ´Ï´Ù.

2. ¾î³ëÅ×À̼ÇÀ» »ç¿ëÇÒ ¿¹Á¦ Ŭ·¡½º ÀÛ¼º

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class AnnotationExam01 {
@InsertIntData(data = 30)
private int myAge;

@InsertIntData
private int defaultAge;

public AnnotationExam01() {
this.myAge = -1;
this.defaultAge = -1;
}

public int getMyAge() {
return myAge;
}

public int getDefaultAge() {
return defaultAge;
}
}
}

º¯¼ö´Â ´ÙÀ½°ú °°ÀÌ myAge¿Í defaultAge µÎ °¡ÁöÀε¥ myAge¿¡ ¾î³ëÅ×À̼ǿ¡¼­´Â 30À¸·Î °ªÀ» ÁÖÀÔÇÕ´Ï´Ù.
ÇÏÁö¸¸ defaultAge ¿¡¼­´Â °ªÀÌ ¾ø´Âµ¥ ÀÌ °æ¿ì ¾î³ëÅ×À̼ǿ¡¼­ Á¤ÇÑ ±âº» °ªÀÎ 0À¸·Î °ªÀÌ ÁÖÀÔÀÌ µË´Ï´Ù.
»ý¼ºÀÚÀÇ °æ¿ì °ªÀÌ ¾øÀ» °æ¿ì -1À» ±âº»À¸·Î ÀúÀåÇÕ´Ï´Ù.

´ÙÀ½Àº µÎ ¹ø° ¿¹Á¦ÀÎ ¹®ÀÚ¿­ °ª ÁÖÀÔÀ» º¸µµ·Ï ÇÏ°Ú½À´Ï´Ù.
µÎ ¹ø° ¿¹Á¦¿¡¼­´Â ¼öÇà Ŭ·¡½º ¹× ½ÇÇà Ŭ·¡½º±îÁö ¾Ë¾Æº¸°Ú½À´Ï´Ù.


2. ¹®ÀÚ¿­ °ª ÁÖÀÔ ¿¹Á¦

µÎ ¹ø° ÁÖÁ¦´Â ¾î³ëÅ×À̼ÇÀ» ¼±¾ðÇÑ Á¤¼öÇü º¯¼ö¿¡ °ªÀ» ³Ö´Â ¿¹Á¦¸¦ ÁøÇàÇغ¸°Ú½À´Ï´Ù.

°£´ÜÇÑ ¿¹Á¦ À̹ǷΠÁÖ¼®Àº ´ÞÁö ¾Ê°Å³ª °£´ÜÇÑ ¼³¸íÀ¸·Î ´ëüÇÏ°Ú½À´Ï´Ù.

1. ¾î³ëÅ×ÀÌ¼Ç ÀÎÅÍÆäÀ̽º ÀÛ¼º

1
2
3
4
5
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InsertStringData {
String data() default "default";
}

À§ÀÇ 1-1¿Í ºñ½ÁÇÕ´Ï´Ù.
±âº» °ªÀ¸·Î´Â default ¹®ÀÚ¿­À» °¡Áý´Ï´Ù.

2. ¾î³ëÅ×À̼ÇÀ» »ç¿ëÇÒ ¿¹Á¦ Ŭ·¡½º ÀÛ¼º

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class AnnotationExam02 {

@InsertStringData(data = "MHLab")
private String myData;

@InsertStringData
private String defaultData;

public AnnotationExam02() {
myData = "No data";
defaultData = "No data";
}

public String getMyData() {
return myData;
}

public String getDefaultData() {
return defaultData;
}
}

º¯¼ö´Â ´ÙÀ½°ú °°ÀÌ myData¿Í defaultData µÎ °¡ÁöÀε¥ myData¿¡ ¾î³ëÅ×À̼ǿ¡¼­´Â ¡°MHLab¡±À¸·Î °ªÀ» ÁÖÀÔÇÕ´Ï´Ù.
ÇÏÁö¸¸ defaultData ¿¡¼­´Â °ªÀÌ ¾ø´Âµ¥ ÀÌ °æ¿ì ¾î³ëÅ×À̼ǿ¡¼­ Á¤ÇÑ ±âº» °ªÀÎ ¡°default¡±·Î °ªÀÌ ÁÖÀÔÀÌ µË´Ï´Ù.
»ý¼ºÀÚÀÇ °æ¿ì °ªÀÌ ¾øÀ» °æ¿ì ¡°No data¡± ¹®ÀÚ¿­À» ±âº»À¸·Î ÀúÀåÇÕ´Ï´Ù.

3. ¾î³ëÅ×À̼ÇÀ» ¼öÇàÇϴ Ŭ·¡½º ÀÛ¼º

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class AnnotationHandler {
private <T> T checkAnnotation(T targetObj, Class annotationObj) {
Field[] fields = targetObj.getClass().getDeclaredFields();
for (Field f : fields) {
if(annotationObj == InsertIntData.class) {
return checkAnnotation4InsertInt(targetObj, f);
}
else if(annotationObj == InsertStringData.class) {
return checkAnnotation4InsertString(targetObj, f);
}
}
return targetObj;
}

private <T> T checkAnnotation4InsertInt(T targetObj, Field field) {
InsertIntData annotation = field.getAnnotation(InsertIntData.class);
if(annotation != null && field.getType() == int.class) {
field.setAccessible(true);
try { field.set(targetObj, annotation.data()); }
catch (IllegalAccessException e) { System.out.println(e.getMessage()); }
}
return targetObj;
}

private <T> T checkAnnotation4InsertString(T targetObj, Field field) {
InsertStringData annotation = field.getAnnotation(InsertStringData.class);
if(annotation != null && field.getType() == String.class) {
field.setAccessible(true);
try { field.set(targetObj, annotation.data()); }
catch (IllegalAccessException e) { System.out.println(e.getMessage()); }
}
return targetObj;
}

public <T> Optional<T> getInstance(Class targetClass, Class annotationClass) {
Optional optional = Optional.empty();
Object object;
try {
object = targetClass.newInstance();
object = checkAnnotation(object, annotationClass);
optional = Optional.of(object);
}catch (InstantiationException | IllegalAccessException e) { System.out.println(e.getMessage()); }
return optional;
}
}

¾à°£ Äڵ尡 º¹ÀâÇѵ¥ Çϳª¾¿ ¼³¸íµå¸®°Ú½À´Ï´Ù.
(ÄÚµå ¸®ÆåÅ丵ÀÌ ÇÊ¿äÇÏÁö¸¸ ¿¹Á¦¸¦ À§ÇÑ ÄÚµåÀ̱⿡ ±×³É ÁøÇàÇÏ°Ú½À´Ï´Ù.)

getInstance ¸Þ¼­µå

ÀÌ ¸Þ¼­µå´Â µÎ °¡ÁöÀÇ Àü´ÞÀÎÀÚ¸¦ ¹Þ½À´Ï´Ù.
ù ¹ø°´Â ¾î³ëÅ×À̼ÇÀÌ Àû¿ëµÇ¾î ÀÖ´Â 2¹ø¿¡¼­ ÀÛ¼ºÇÑ Å¬·¡½º, µÎ ¹ø°´Â üũÇÒ ¾î³ëÅ×ÀÌ¼Ç Å¬·¡½ºÀÔ´Ï´Ù.
¹Ýȯ °ªÀº OptionalÀ» »ç¿ëÇÏ¿© ¹ÝȯÇÏ°Ô µË´Ï´Ù.
¸ÕÀú Ÿ°Ù Ŭ·¡½ºÀÇ ÀνºÅϽº¸¦ »ý¼ºÇÏ°í, checkAnnotation ¸Þ¼­µå¸¦ È£ÃâÇÕ´Ï´Ù.
¿©±â¼­ Àü´ÞÀÎÀÚ¿¡ ¾î³ëÅ×ÀÌ¼Ç Å¬·¡½º¸¦ ³ÖÀº °ÍÀº ÇâÈÄ È®À强À» °í·Á ÇÏ¿´´Âµ¥, ÀÌ ºÎºÐÀº ±âÈ£¿¡ ¾Ë¸Â°Ô ¸Þ¼­µå¸¦ ³ª´²¼­ ±¸ÇöÀ» Çصµ ¹«¹æÇÕ´Ï´Ù.

checkAnnotation ¸Þ¼­µå

ÀÌ ¸Þ¼­µå´Â ¾Õ¼± getInstance ¸Þ¼­µåÀÇ Àü´ÞÀÎÀÚ¸¦ ±×´ë·Î ¹Þ½À´Ï´Ù.
fields º¯¼ö´Â Ÿ°Ù °´Ã¼¿¡ ¼±¾ðµÈ °ÍµéÀ» ¸ðµÎ °¡Á®¿É´Ï´Ù. (Field´Â ¸®Ç÷º¼Ç°ú °ü·ÃµÇ¾î ÀÖ°í, ÀÌ´Â ´ÙÀ½ Æ÷½ºÆÿ¡¼­ ´Ù·ç°Ú½À´Ï´Ù.)
±× ´ÙÀ½ Àü´ÞÀÎÀÚ annotationObj °ª¿¡ µû¶ó ºÐ±â¸¦ ³ª´² ¸Þ¼­µå¸¦ È£ÃâÇÏ°Ô µË´Ï´Ù.

checkAnnotation4InsertInt ¸Þ¼­µå (checkAnnotation4InsertString ¸Þ¼­µåµµ µ¿ÀÛÀÌ ºñ½ÁÇÏ°Ô ¿©±â ¼³¸íÀ¸·Î ´ëüÇÕ´Ï´Ù.)

ÇØ´ç ¸Þ¼­µå´Â ÇÑ ¶óÀξ¿ °£·«ÇÏ°Ô Â¤°í ³Ñ¾î°¡°Ú½À´Ï´Ù

InsertIntData annotation = field.getAnnotation(InsertIntData.class);
ÀÌ ºÎºÐÀº Àü´ÞÀÎÀÚ·Î ¹ÞÀº Field¿¡¼­ ¼±¾ðµÈ ¾î³ëÅ×À̼ÇÀ» °¡Á®¿É´Ï´Ù.

if(annotation != null && field.getType() == int.class)
ÀÌ ºÎºÐÀº ¾î³ëÅ×À̼ÇÀÌ nullÀÌ ¾Æ´Ï°Å³ª ¼±¾ðµÈ º¯¼öÀÇ Å¸ÀÔÀÌ intÇüÀÏ °æ¿ì¿¡¸¸ ¼öÇàÀ» ÇÏ°Ô µË´Ï´Ù.

field.setAccessible(true);
ÀϹÝÀûÀ¸·Î private·Î ¼±¾ðµÈ º¯¼ö(Çʵå)ÀÇ °æ¿ì Á¢±ÙÀÌ ºÒ°¡´ÉÇÏÁö¸¸, ¸®Ç÷ºÆ®¸¦ ÅëÇÑ Á¢±Ù¿¡ ÇÑÇÏ¿© °¡´ÉÇÏ°Ô²û ÇØÁØ´Ù.

try { field.set(targetObj, annotation.data()); }
ÇØ´ç º¯¼öÀÇ °ªÀ» ¾î³ëÅ×À̼ÇÀÇ °ªÀ¸·Î ġȯÇÏ°Ô µË´Ï´Ù.

À§¿Í °°Àº ÀÛ¾÷À» °ÅÄ¡°í ³­ ÈÄ Àü´ÞÀÎÀÚ·Î ³Ñ¾î¿Â ¾î³ëÅ×À̼ÇÀÌ ¼±¾ðµÈ Ŭ·¡½º °´Ã¼¸¦ ¹ÝȯÇÏ°Ô µË´Ï´Ù.


4. ½ÇÇà Ŭ·¡½º ÀÛ¼º

¾Æ·¡´Â À§ÀÇ µÎ °¡Áö ¿¹Á¦ÀÇ ½ÇÇàÄڵ带 ÀÛ¼ºÇÏ¿´½À´Ï´Ù.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
AnnotationHandler handler = new AnnotationHandler();
AnnotationExam01 exam01 = handler.getInstance(AnnotationExam01.class, InsertIntData.class)
.map(o -> (AnnotationExam01)o)
.orElse(new AnnotationExam01());

AnnotationExam02 exam02 = handler.getInstance(AnnotationExam02.class, InsertStringData.class)
.map(o -> (AnnotationExam02)o)
.orElse(new AnnotationExam02());

System.out.println("myAge = " + exam01.getMyAge());
System.out.println("defaultAge = " + exam01.getDefaultAge());

System.out.println("myData = " + exam02.getMyData());
System.out.println("defaultData = " + exam02.getDefaultData());
}

½ÇÇà°á°ú´Â ´ÙÀ½°ú °°ÀÌ Ãâ·ÂµË´Ï´Ù.

myAge = 30
defaultAge = -1
myData = MHLab
defaultData = No data
Process finished with exit code 0


Á¤¸®

¹º°¡ ±ÛÀÌ º¹ÀâÇÏ°í ÀåȲÇÏ°Ô ¾´ °Í °°Áö¸¸¡¦ÃÖ´ëÇÑ ³»¿ëÀ» ½±°Ô Ç®¾î¼­ ÀÛ¼ºÇÏ¿´½À´Ï´Ù.
À߸øµÇ¾ú°Å³ª ¹®Á¦°¡ ÀÖ´Â ºÎºÐÀº ¾Ë·ÁÁÖ½Ã¸é ¼öÁ¤Çϵµ·Ï ÇÏ°Ú½À´Ï´Ù.