๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Java·๏ปฟServlet·๏ปฟJSP

[JAVA/์›น] Annotation๊ณผ Reflections ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ž๋ฐ” ๋นˆ ๊ด€๋ฆฌํ•˜๊ธฐ

by Leica 2020. 2. 21.
๋ฐ˜์‘ํ˜•

[JAVA] Annotation๊ณผ Reflections ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ž๋ฐ” ๋นˆ ๊ด€๋ฆฌํ•˜๊ธฐ

Java Annotation(์ž๋ฐ” ์–ด๋…ธํ…Œ์ด์…˜)

์–ด๋…ธํ…Œ์ด์…˜์€ ์ปดํŒŒ์ผ, ๋ฐฐํฌ, ์‹คํ–‰ ์‹œ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š” ํŠน๋ณ„ํ•œ ์ฃผ์„์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค. ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ํด๋ž˜์Šค, ํ•„๋“œ, ๋ฉ”์†Œ๋“œ์— ๋ถ€๊ฐ€ ์ •๋ณด๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋‹ค.

์–ด๋…ธํ…Œ์ด์…˜์„ ์ด์šฉํ•ด์„œ ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹œ์ž‘๋  ๋•Œ ์ƒ์„ฑ์ด ํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด๋ณด์ž.

 

์–ด๋…ธํ…Œ์ด์…˜ ์ •์˜

Component.java

1
2
3
4
5
6
7
8
9
/*์–ด๋…ธํ…Œ์ด์…˜ ์œ ์ง€ ์ •์ฑ… - RetentionPolicy.RUNTIME:
* ํด๋ž˜์Šค ํŒŒ์ผ์— ๊ธฐ๋ก๋จ
* ์‹คํ–‰ ์‹œ์— ์œ ์ง€๋จ
* ์‹คํ–‰ ์ค‘ ํด๋ž˜์Šค์— ๊ธฐ๋ก๋œ ์–ด๋…ธํ…Œ์ด์…˜ ๊ฐ’ ์ฐธ์กฐ ๊ฐ€๋Šฅ
* */
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
    String value() default "";
}
cs

 

์–ด๋…ธํ…Œ์ด์…˜์€ ์œ„์™€ ๊ฐ™์ด ์ •์˜ํ•œ๋‹ค.

์–ด๋…ธํ…Œ์ด์…˜ ๋ฌธ๋ฒ•์€ ์ธํ„ฐํŽ˜์ด์Šค์™€ ๋น„์Šทํ•˜๋‹ค.

interface ํ‚ค์›Œ๋“œ ์•ž์— '@'๊ฐ€ ๋ถ™๋Š”๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค์—์„œ ๋ฉ”์†Œ๋“œ๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ ์–ด๋…ธํ…Œ์ด์…˜์—์„œ๋Š” ์†์„ฑ์„ ์ •์˜ํ•œ๋‹ค.

์†์„ฑ ์ค‘ value()๋Š” ์†์„ฑ ์ด๋ฆ„์„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค.

@Component(value="์†์„ฑ๊ฐ’") = @Component("์†์„ฑ๊ฐ’")

 

default ํ‚ค์›Œ๋“œ๋กœ ์†์„ฑ์˜ ๊ธฐ๋ณธ๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ง€๊ธˆ์€ ์†์„ฑ๊ฐ’์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋นˆ ๋ฌธ์ž์—ด("")์ด ๊ธฐ๋ณธ๊ฐ’์ด ๋˜๋„๋ก ํ•˜์˜€๋‹ค.

 

@Retention() - ์–ด๋…ธํ…Œ์ด์…˜ ์œ ์ง€ ์ •์ฑ…

์–ด๋…ธํ…Œ์ด์…˜์„ ์ •์˜ํ• ๋•Œ๋Š” @Retention()์œผ๋กœ ๋ฐ˜๋“œ์‹œ ์–ด๋…ธํ…Œ์ด์…˜์˜ ์œ ์ง€ ์ •์ฑ…์„ ์ง€์ •ํ•ด์•ผํ•œ๋‹ค.

์–ด๋…ธํ…Œ์ด์…˜ ์œ ์ง€ ์ •์ฑ…์€ ์–ด๋…ธํ…Œ์ด์…˜ ์ •๋ณด๋ฅผ ์–ธ์ œ๊นŒ์ง€ ์œ ์ง€ํ• ๊ฒƒ์ธ์ง€ ์„ค์ •ํ•˜๋Š” ๋ฌธ๋ฒ•์ด๋‹ค.

 

์•ž์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ์–ด๋…ธํ…Œ์ด์…˜ ์œ ์ง€ ์ •์ฑ…์„ RUNTIME์œผ๋กœ ์ง€์ •ํ•˜๋ฉด ์‹คํ–‰ ์ค‘์—๋„ @Component ์–ด๋…ธํ…Œ์ด์…˜์˜ ์†์„ฑ๊ฐ’์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์–ด๋…ธํ…Œ์ด์…˜ ์œ ์ง€ ์ •์ฑ… ์„ค๋ช…
Retention.SOURCE ์†Œ์Šค ํŒŒ์ผ์—์„œ๋งŒ ์œ ์ง€๋˜๊ณ  ์ปดํŒŒ์ผ ์‹œ ์ œ๊ฑฐ๋จ
Retention.CLASS (๊ธฐ๋ณธ ์ •์ฑ…) ํด๋ž˜์Šค ํŒŒ์ผ์— ๊ธฐ๋ก๋˜๊ณ  ์‹คํ–‰ ์‹œ์—๋Š” ์œ ์ง€๋˜์ง€ ์•Š์Œ
Retention.RUNTIME ํด๋ž˜์Šค ํŒŒ์ผ์— ๊ธฐ๋ก๋˜๊ณ  ์‹คํ–‰ ์‹œ์—๋„ ์œ ์ง€๋จ
์‹คํ–‰ ์ค‘ ํด๋ž˜์Šค์— ๊ธฐ๋ก๋œ ์–ด๋…ธํ…Œ์ด์…˜ ๊ฐ’์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Œ

 

์–ด๋…ธํ…Œ์ด์…˜ ์ ์šฉ

์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘ ์‹œ Component ์–ด๋…ธํ…Œ์ด์…˜์ด ์ง€์ •๋œ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ์ค€๋น„ํ•˜๋„๋ก ํ•  ๊ฒƒ์ด๋‹ค.

์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘ ์‹œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ํด๋ž˜์Šค์— ์–ด๋…ธํ…Œ์ด์…˜์„ ์„ ์–ธํ•œ๋‹ค.

์„ ์–ธ ๋ฐฉ๋ฒ•์€ ํด๋ž˜์Šค ์„ ์–ธ๋ถ€ ์œ„์— @์–ด๋…ธํ…Œ์ด์…˜๋ช…("์†์„ฑ๊ฐ’")๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

 

1
2
3
@Component("/auth/login.do")
public class LogInController implements Controller, DataBinding {
...
cs

 

์ปจํŠธ๋กค๋Ÿฌ์— ์„œ๋ธ”๋ฆฟ URL์„ ์†์„ฑ๊ฐ’์œผ๋กœ ํ•˜์—ฌ ์–ด๋…ธํ…Œ์ด์…˜์„ ์„ ์–ธํ•ด์ฃผ์—ˆ๋‹ค.

 

Reflections ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค€๋น„

Reflections๋Š” ๊ตฌ๊ธ€ ์ฝ”๋“œ ์‚ฌ์ดํŠธ์— ๋“ฑ๋ก๋œ ์˜คํ”ˆ ์†Œ์Šค ํ”„๋กœ์ ํŠธ์ด๋‹ค. ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•˜๋ฉด ์ž๋ฐ” ๋ฆฌํ”Œ๋ž™์…˜ API๋ณด๋‹ค ๋” ์‰ฝ๊ณ  ํŽธํ•˜๊ฒŒ ํด๋ž˜์Šค๋ฅผ ์ฐพ๊ณ  ์ •๋ณด๋ฅผ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

 

https://code.google.com/archive/p/reflections/downloads ์—์„œ Reflections ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋‹ค์šด๋กœ๋“œ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

Downloads ํŽ˜์ด์ง€์—์„œ reflections-0.9.9-RC1-uberjar.jar, reflections-0.9.9-RC1.jar ์„ ๋‹ค์šด๋กœ๋“œ ๋ฐ›๋Š”๋‹ค.

reflections-0.9.9-RC1.jar๋Š” Reflections ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๊ณ  reflections-0.9.9-RC1-uberjar.jar์—๋Š” ์˜์กด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ๋“ค์–ด์žˆ๋‹ค.

reflections-0.9.9-RC1.jar๋Š” ๊ทธ๋Œ€๋กœ ๋‘๊ณ  reflections-0.9.9-RC1-uberjar.jar๋Š” ์••์ถ•์„ ํ’€์–ด๋‘”๋‹ค.

 

reflections-0.9.9-RC1.jar์™€ reflections-0.9.9-RC1-uberjar.jar ์•ˆ์˜ jarํŒŒ์ผ๋“ค์„ ํ”„๋กœ์ ํŠธ์— ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

 

๊ฐ์ฒด ์ƒ์„ฑ ๋ฉ”์†Œ๋“œ ๊ตฌํ˜„

์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹œ์ž‘๋  ๋•Œ ์ƒ์„ฑ๋˜๋Š” ํด๋ž˜์Šค์— @Component ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค.

์ฐธ๊ณ ๋กœ ํ†ฐ์บฃ์˜ ๊ฒฝ์šฐ ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹œ์ž‘๋  ๋•Œ ServletContextListener ๊ตฌํ˜„์ฒด์˜ contextInitialized() ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค. ์ž์„ธํ•œ ๊ฒƒ์€ ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•˜์ž.

 

์ฐธ๊ณ  : ServletContextListener๋กœ DB ์ปค๋„ฅ์…˜, DAO ๊ณต์œ  ๊ฐ์ฒด ๊ด€๋ฆฌํ•˜๊ธฐ

 

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
Map<String, Object> objTable = new Hashtable<>();
 
// ๊ฐ์ฒด๋ฅผ ๊บผ๋‚ผ getter
public Object getBean(String key) {
    return objTable.get(key);
}
 
/**
 * classpath๋ฅผ ๋’ค์ ธ์„œ Component ์–ด๋…ธํ…Œ์ด์…˜์ด ์ง€์ •๋œ ํด๋ž˜์Šค๋ฅผ ์ฐพ์€๋’ค ํ•ด๋‹น ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ์ค€๋น„ํ•œ๋‹ค.
 * ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋Š” ๊ฐ์ฒด ํ…Œ์ด๋ธ”์— ๋‹ด๋Š”๋‹ค.
 * ์˜คํ”ˆ์†Œ์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ Reflections ์‚ฌ์šฉ: ์ž๋ฐ” ๋ฆฌํ”Œ๋ž™์…˜ API๋ณด๋‹ค ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ณ  ํŽธํ•จ
 * @throws Exception
 */
private void prepareAnnotationObjects() throws Exception {
    // Reflections ํด๋ž˜์Šค๋Š” ์›ํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ
    // ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ’์€ ํด๋ž˜์Šค๋ฅผ ์ฐพ์„๋•Œ ์ถœ๋ฐœ ํŒจํ‚ค์ง€
    // "" -> classpath ๋ชจ๋“  ํŒจํ‚ค์ง€ ๊ฒ€์ƒ‰
    Reflections reflector = new Reflections("");
    // getTypesAnnotatedWith():
    // ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ’์œผ๋กœ ๋„˜๊ธด ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ํด๋ž˜์Šค๋ฅผ ์ฐพ๋Š”๋‹ค.
    // ๋ฐ˜ํ™˜๊ฐ’: @Component ์–ด๋…ธํ…Œ์ด์…˜์ด ์„ ์–ธ๋œ ํด๋ž˜์Šค ๋ชฉ๋ก
    Set<Class<?>> list = reflector.getTypesAnnotatedWith(Component.class);
    String key = null;
    for(Class<?> clazz: list) {
        // getAnnotation(): ํด๋ž˜์Šค๋กœ๋ถ€ํ„ฐ ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”์ถœ
        key = clazz.getAnnotation(Component.class).value();
        objTable.put(key, clazz.getDeclaredConstructor().newInstance());
        System.out.println(clazz.getName() + "(" + key + ") -> ๊ฐ์ฒด ์ค€๋น„ ์™„๋ฃŒ");
    }
}
cs

๊ฒฐ๊ณผ ํ™•์ธ์„ ์œ„ํ•ด ์ถœ๋ ฅ๋ฌธ์„ ์ž‘์„ฑํ•ด๋‘์—ˆ๋‹ค.

 

1) Reflections

Reflections ์ƒ์„ฑ์ž์— ๋„˜๊ฒจ์ฃผ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์€ ํด๋ž˜์Šค๋ฅผ ์ฐพ์„๋•Œ์˜ ์ถœ๋ฐœ ํŒจํ‚ค์ง€์ด๋‹ค. ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์ด "com.atoz_develop"์ด๋ฉด com.atoz_develop ํŒจํ‚ค์ง€์™€ ๊ทธ ํ•˜์œ„ ํŒจํ‚ค์ง€๋ฅผ ๋ชจ๋‘ ์ฐพ๋Š”๋‹ค. ๋นˆ ๋ฌธ์ž์—ด์„ ๋„˜๊ธฐ๋ฉด ์ž๋ฐ” classpath์— ์žˆ๋Š” ๋ชจ๋“  ํŒจํ‚ค์ง€๋ฅผ ์ฐพ๋Š”๋‹ค.

 

2) getTypesAnnotatedWith()

์ด ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ• ๋•Œ ์–ด๋…ธํ…Œ์ด์…˜์˜ ํด๋ž˜์Šค๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ฒจ ํ•ด๋‹น ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ํด๋ž˜์Šค๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค.

getTypesAnnotatedWith(Component.class)์™€ ๊ฐ™์ด ํ˜ธ์ถœํ•˜๋ฉด @Component ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ํด๋ž˜์Šค๋ฅผ ์ฐพ๋Š”๋‹ค.

๋ฐ˜ํ™˜๊ฐ’์€ ํ•ด๋‹น ์–ด๋…ธํ…Œ์ด์…˜์ด ์„ ์–ธ๋œ ํด๋ž˜์Šค ๋ชฉ๋ก์ด๋‹ค.

 

3) getAnnotation().value()

getAnnotation()์„ ํ†ตํ•ด ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”์ถœํ•œ๋‹ค.

์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”์ถœํ•˜๋ฉด ํ•ด๋‹น ์–ด๋…ธํ…Œ์ด์…˜์— ์ •์˜๋œ ๋ฉ”์†Œ๋“œ(์†์„ฑ)์„ ํ˜ธ์ถœํ•ด์„œ ์†์„ฑ ๊ฐ’์„ ๊บผ๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

Component ์–ด๋…ธํ…Œ์ด์…˜์—๋Š” value() ์†์„ฑ์ด ์ •์˜๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ value()๋ฅผ ํ˜ธ์ถœํ•ด์„œ value()์— ์„ค์ •๋œ ๊ฐ’์„ ๊บผ๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๊บผ๋‚ธ ๊ฐ’์„ key๋กœ ํ•˜์—ฌ ํ•„์š”ํ•œ ๊ณณ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•œ๋‹ค.

 

์ด์ œ ํ†ฐ์บฃ์„ ๊ตฌ๋™ํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•ด๋ณด์ž.

 

์œ„์™€ ๊ฐ™์ด ํ†ฐ์บฃ ๊ตฌ๋™์ด ์™„๋ฃŒ๋˜๋ฉด Component ์–ด๋…ธํ…Œ์ด์…˜์„ ์„ ์–ธํ•œ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉฐ ๊ฐ์ฒด๊ฐ€ ์ค€๋น„๋œ๋‹ค.

 

์ด๋ ‡๊ฒŒ ํ•จ์œผ๋กœ์จ ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘ ์‹œ ์ค€๋น„ํ•ด์•ผํ•  ๊ฐ์ฒด๊ฐ€ ์ถ”๊ฐ€๋˜๋ฉด @Component ์–ด๋…ธํ…Œ์ด์…˜์„ ์„ ์–ธํ•ด์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€