<๊ฐ์>
์ ๋ฒ ์๊ฐ์ ๋ฐฐ์ ๋ ๋ด์ฉ์ (main2.java)ํด๋์ค์ ๊ฒฝ๋ก์ฃผ์๊ฐ ๋ค์ด๊ฐ ์๋ ์ธ๋ถ ์ ์ฅ ํ์ผ (.porperties)์์ Key= ๊ฐ์ฒด์ด๋ฆ, Value= ํด๋์ค์ ๊ฒฝ๋ก์ฃผ์๋ก ๊ฐ ๋ฝ์๋ด์ ๊ฐ์ฒด ์ ์ฅ์๋ map์ ์ ์ฅํ๋ค. ํด๋น map์์ ๋ค์ value์ ๊ฒฝ๋ก์ฃผ์๋ฅผ ํตํด ์ง์ง ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ๋ด์ value ๊ฐ๋ค์ ๊ฐฑ์ ํ๋ค.
๊ฒฐ๊ตญ map์ (K(๊ฐ์ฒด์ด๋ฆ), V(๊ฐ์ฒด))๊ฐ ๋์ด์ ์ฌ์ฉ์๊ฐ ์ด๋ค ๊ฐ์ฒด๋ฅผ ์ ์ธํ๋ คํ๋ฉด, new๋ฅผ ์ด์ฉํด ๋์ ํ ๋น ํ์ง ์๊ณ map์์ ์ฐพ์ ๊บผ๋ด ์ผ๋ค.
๊ทธ๋ค์ main3.java์์ ๋ฐฐ์ด ๋ด์ฉ์ ์ปดํฌ๋ํธ ์ด๋ ธํ ์ด์ ์ ์ด์ฉํ๋ ๊ฒ์ด์๋ค. ๋จผ์ ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ ํด๋์ค๋ค์๋ @Component๋ฅผ ๋ถ์ธ๋ค. ๊ทธ๋ฆฌ๊ณ doComponentScan์ด๋ผ๋ ํจ์๋ฅผ ๋ง๋ ๋ค. ํด๋น ํจ์๋ ํจํค์ง ๋ด์ ๋ชจ๋ ํด๋์ค๋ฅผ ์ฝ์ด์ set์ด๋ ์ปฌ๋ ์ ํ๋ ์์ํฌ์ ์ ์ฅํ๊ณ , set์ ์ ์ฅ๋ ํด๋์ค๋ฅผ ํ๋์ฉ ์ฝ์ด์ ์ปดํฌ๋ํธ๊ฐ ์๋์ง ํ์ธํ ํ, ์ปดํฌ๋ํธ๊ฐ ๋ถ์ด ์์ผ๋ฉด map์ (K(Class์ด๋ฆ์ ์๊ธ์๋ง ์๋ฌธ์๋ก ๋ฐ๊พผ ์ด๋ฆ), V(ํด๋น ํด๋์ค์ ๊ฐ์ฒด))๋ก ๋ง๋ค์ด ์ ์ฅํ๋ค.
๊ทธ ํ ์ฌ์ฉ์๊ฐ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ผ์ด ์์ผ๋ฉด ํด๋น Map์์ ์ฐพ์๋ด์ ์ผ๋ค.
์ด๋ฒ์ ๋ฐฐ์ธ ๋ด์ฉ์ main3.java์์ ํ ๋จ๊ณ ๋ ๋์๊ฐ ๊ฒ์ผ๋ก Car๋ผ๋ ๊ฐ์ฒด๊ฐ iv๋ก ๋ค๋ฅธ ํด๋์ค์ ๊ฐ์ฒด๋ค์ ์ง๋๊ณ ์๋ ๊ฒฝ์ฐ์ด๋ค. ์ด ๊ฒฝ์ฐ, ๊ทธ์ ๊ฐ์ฒด๋ค์ ์์ฑํ ๊ฒ์์ ๋๋์ง ์๊ณ , Car์ iv ์ธ ๊ฐ์ฒด๋ค์ ์์ฑ๋ ๊ฐ์ฒด๋ค์ ์ฐ๊ฒฐํด์ฃผ์ด์ผ ํ๋ค.
๋ฌผ๋ก ์๋์ผ๋ก ํ ์ ์์ง๋ง, ์ด๋ฅผ ์๋์ผ๋ก ํ๋ ๋ฒ์ ๋ํด์ ๋ฐฐ์ฐ๊ฒ ๋ค. ์๋์ผ๋ก ํ๋ ๋ฒ์ ์ด 2๊ฐ์ง์ธ๋ฐ ํ๋๋
@AutoWired ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ ๋ฒ, ํ๋๋ @Resource ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ ๋ฒ์ด๋ค.
1. Map์์ ํด๋์ค ํ์ ์ผ๋ก ๊ฐ์ฒด ๊ฒ์
Object getBean(String key) {return map.get(key);} // by name
Car car = (Car)ac.getBean("car"); // byName์ผ๋ก ๊ฐ์ฒด๋ฅผ ๊ฒ์
์ ํจ์๋Map์ Key๋ฅผ ์ด์ฉํด ๊ฐ์ฒด๋ฅผ ์ฐพ๋ Method์ด๋ค. ํด๋น ๋งค์๋๋ Key ๊ฐ ,๊ทธ๋ฌ๋๊น ๊ฐ์ฒด์ ์ด๋ฆ์ ์ฃผ๋ฉด ํด๋น ์ด๋ฆ์ Key๋ก ๊ฐ์ง ์์์ Value ๊ฐ(๊ฐ์ฒด)์ ๋ฆฌํดํด์ฃผ์๋ค.
์ด๋ฒ์๋ Map์ Value ๊ฐ ์์ฒด๋ฅผ ๋ค์ ธ์ ์ผ์นํ๋ ๊ฐ์ฒด๋ฅผ ์ฐพ์๋ด๋ ๋ฐฉ๋ฒ์ ์์๋ณด๊ฒ ๋ค.
Object getBean(Class clazz ) { // by type
for (Object obj :
map.values()) {
// obj๊ฐ clazz ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๊ตฌํํ ํด๋์ค์ ๊ฐ์ฒด๋ผ๋ฉด, (์ฌ๊ธฐ์ ๊ฐ์ฒด๋ ์์ ํด๋์ค์ ๊ฐ์ฒด๋ ์๊ด ๋ฌด)
if (clazz.isInstance(obj))
return obj;
}
return null;
}
/* ์ด๋ค ํด๋์ค์ ๋ฉํ๋ฐ์ดํฐ๊ฐ ์ธ์๋ก ๋ค์ด์ค๋ฉด,
map ๋ด์์ ํด๋น ํด๋์ค์ ๊ฐ์ฒด์ด๊ฑฐ๋ ์์์ธ ๋
์์ด ์๋์ง ์ฐจ๋ก๋๋ก ์ฐพ๊ณ ,
๋ง์ฝ ๋ฐ๊ฒฌํ๋ฉด ๊ทธ๋
์์ return */
/*์ฌ์ฉํ๋ ์์*/
// ์ด๋ค ํด๋์ค์ ๋ฉํ๋ฐ์ดํฐ๋ก ๊ฒ์
Door door = (Door)ac.getBean(Door.class);
//map ๋ด์ door๋ผ๋ ํ์
์ ๊ฐ์ฒด๊ฐ ์๋์ง ๋ค์ง๋ค.
2. @AutoWired ์ด๋ ธํ ์ด์ ํ์ฉ
Map์์ ๊ฐ์ฒด๋ฅผ ์ฐพ๋ 2๊ฐ์ง ๋ฐฉ๋ฒ์ ์ด์ ์์๋ดค๊ณ , ๊ฐ์ฒด ์ฌ์ด์ ๊ด๊ณ๋ฅผ ์๋ 2๊ฐ์ง ๋ฐฉ๋ฒ์ ์์๋ณด๊ฒ ๋ค.
๋จผ์ ์์ ์ํฉ์ด๋ค.
@Component class Car {
Engine engine;
Door door;
}
}
@Component class SportsCar extends Car {}
@Component class Truck extends Car{}
@Component class Engine {}
@Component class Door {}
Car๋ผ๋ ๊ฐ์ฒด์ ์ธ์คํด์ค ๋ณ์๋ก Engine๊ณผ Door์ ๊ฐ์ฒด๊ฐ ๋ค์ด๊ฐ ์๋ค.
@Component ๋ฐฉ์์ ์ผ์ผ๋ฏ๋ก, Map์ ์ด์ฉํ ๊ฐ์ฒด ์์ฑ์ ์ํํ๊ฒ ๋์๋ค.
Car car = (Car)ac.getBean("car"); // byName์ผ๋ก ๊ฐ์ฒด๋ฅผ ๊ฒ์
Engine engine = (Engine)ac.getBean("engine");
Door door = (Door)ac.getBean(Door.class); // by Type์ผ๋ก ๊ฐ์ฒด ๊ฒ์
ํ์ง๋ง ์ด ๊ฒฝ์ฐ ์ ์ธ๋ง ํ ๊ฒ์ด์ง Car์ iv๋ก ๋ ๊ฐ์ฒด๊ฐ ๋์ ๋ ๊ฒ์ ์๋๋ค.
์ด๊ฑธ ์๋์ผ๋ก ํด์ฃผ๋ ๋ฐฉ๋ฒ๋ ์๋ค.
// ์๋์ผ๋ก ๊ฐ์ฒด๋ฅผ ์ฐ๊ฒฐ
// car.engine = engine;
// car.door = door;
์ด์ AutoWired๋ฅผ ์ด์ฉํด ์๋์ผ๋ก ํ๋ ๋ฒ์ ๋ฐฐ์๋ณด๊ฒ ๋ค.
๋จผ์ Car ๊ฐ์ฒด์ ์ธ์คํด์ค ๋ณ์ ์ค ๊ฐ์ฒด์ธ ๊ฒ์ @AutoWired ํ๊ทธ๋ฅผ ๋ถ์ธ๋ค.
@Component class Car {
@Resource
Engine engine;
@Resource
Door door;
}
๊ฐ์ฒด ์ ์ฅ์ ์์ฑ์์
์์ฑ๋ ์ ์คํํ ๋งค์๋๋ฅผ ํ๋ ๋ ๋๋ฆฐ๋ค.
class AppContext {
Map map ; //๊ฐ์ฒด ์ ์ฅ์
AppContext(){
// 1. ์ ์ฅ์ ์์ฑ
map = new HashMap();
// 2. @Component ์ด๋
ธํ
์ด์
๋ถ์ ํด๋์ค๋ค ์๋ ๊ฐ์ฒด ์์ฑ ํด์ (๊ฐ์ฒด์ด๋ฆ, ๊ฐ์ฒด)๋ก Map์ ์ ์ฅ
// ์ฐ๋ฆฐ ์ด์ ์ง์ ๊ฐ์ฒด ์ ์ธ ํ ๋นํ ํ์ ์์ด, Map์์ ํ์ํ ๊ฐ์ฒด๋ฅผ ๋ค์ ธ์ ์ฌ์ฉํ ์ ์๊ฒ ๋จ.
doComponentScan();
// 3. ๋ง์ฝ A ํด๋์ค ์์ ์ธ์คํด์ค ๋ณ์๋ก B ํด๋์ค์ ๊ฐ์ฒด๊ฐ ์์ ์
// A ํด๋์ค๊ฐ ์์ฑ๋๊ณ B ํด๋์ค๊ฐ ์์ฑ๋์์ ๋, ๋์ ๊ด๊ณ๋ฅผ ์ฐ๊ฒฐํด์ฃผ๋ ๊ฒ
// B๊ฐ ์๋์ผ๋ก A์ ์ธ์คํด์ค ๋ณ์๋ก ๋ค์ด๊ฐ.
doAutoWired();
doResource();
}
private void doAutoWired() {
// map์ ์ ์ฅ๋ ๊ฐ์ฒด์ iv ์ค์ @AutoWired๊ฐ ๋ถ์ด ์์ผ๋ฉด
// map์์ iv์ ํ์
์ ๋ง๋ ๊ฐ์ฒด๋ฅผ ์ฐพ์์ ์ฐ๊ฒฐ (์ฐ๊ฒฐํ๋ค๋ ๊ฒ์? ํด๋น ๊ฐ์ฒด์ ์ฃผ์๋ฅผ iv์ ์ ์ฅ)
// bean์ Map์ ์๋ ๋ชจ๋ Value
for (Object bean :
map.values()) {
// fid๋ ํ๋ ํด๋์ค๋ก ํด๋์ค์ ๋ชจ๋ ๋ณ์๋ค์ด ๋ค์ด๊ฐ ์ ์๋ ๊ณณ์ด๊ณ ,
// Map์ Value์๋ ๊ฐ์ฒด๊ฐ ์์ผ๋๊น,
// ๊ทธ ๊ฐ์ฒด๋ฅผ ๋ฉํ๋ฐ์ดํฐ๋ก ๋ถํดํด์ ์ ๊ทผ์ ์ด์ ์๊ด์์ด ๊ฐ์ฒด ์์ ๋ชจ๋ ํ๋์ ์ ๊ทผํจ.
for (Field fid : bean.getClass().getDeclaredFields()) {
// ๋ง์ฝ ์ ๊ทผํ ํ๋ ์ค @Autowired๋ผ๋ ์ด๋
ธํ
์ด์
๊ฐ์ง ํ๋๊ฐ ์๋ค๋ฉด
if(fid.getAnnotation(Autowired.class) != null){ // by type
try {
//์ธ์คํด์ค ๋ณ์๋ก ์๋ ํด๋์ค์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ getBean์ ์ธ์๋ก ์ง์ด ๋ฃ์.
fid.set(bean, getBean(fid.getType())); //car.engine = obj ; ๋์
์ฐ์ฐ
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
}
3. @Resource ์ด๋ ธํ ์ด์ ํ์ฉ
@AutoWired๊ฐ ์ธ์คํด์ค ๋ณ์๋ก ์๋ ํด๋์ค์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ํ์ฉํด Map์ Value(๊ฐ์ฒด)์์ ์ผ์นํ๋ Type์ ๊ฐ์ฒด๋ฅผ ์ฐพ์๋ค๋ฉด @Resource๋ ์ธ์คํด์ค ๋ณ์๋ก ์๋ ํด๋์ค์ ๊ฐ์ฒด ์ด๋ฆ์ ์ด์ฉํ์ฌ Map์ Key(๊ฐ์ฒด ์ด๋ฆ) ์ค์์ ์ด์ ์ผ์นํ๋ ๊ฐ์ฒด๋ฅผ ์ฐพ๋๋ค.
๊ทธ๋ ๋ค๋ฉด, ๊ฐ์ฒด ์ด๋ฆ์ ์ด๋ป๊ฒ ์๊น? @Resource Engine์ด๋ฉด, ํด๋น ํด๋์ค์ ์ฒซ ๋๋ฌธ์๋ฅผ ์๋ฌธ์๋ก ๋ฐ๊พผ ์ด๋ฆ์ ๊ฐ์ฒด ์ด๋ฆ์ผ๋ก ๊ฐ์ฃผํ๊ณ ์ฐพ๋๋ค. (default) ์ฌ์ค @Resource Engine์ @Resource (name = "engine") Engine์ ์ค์๋ง์ด๋ค.
์ฐ๋ฆฌ๊ฐ (name = "")๋ฅผ ์ค๊ฐ์ ์จ์ ๊ฐ์ฒด ์ด๋ฆ์ ์ง์ ํ ์ ๋ ์๋ค.
private void doResource() {
// map์ ์ ์ฅ๋ ๊ฐ์ฒด์ iv ์ค์ @Resource๊ฐ ๋ถ์ด ์์ผ๋ฉด
// map์์ iv์ ์ด๋ฆ์ ๋ง๋ ๊ฐ์ฒด๋ฅผ ์ฐพ์์ ์ฐ๊ฒฐ (์ฐ๊ฒฐํ๋ค๋ ๊ฒ์? ํด๋น ๊ฐ์ฒด์ ์ฃผ์๋ฅผ iv์ ์ ์ฅ)
for (Object bean :
map.values()) {
// bean์ด๋ผ๋ ๊ฐ์ฒด๋ฅผ ๋ฉํ๋ฐ์ดํฐ๋ก ๋ถํดํด์ ํด๋น ๊ฐ์ฒด์ ๋ชจ๋ ํ๋(๋ณ์)์ ์ ๊ทผ
for (Field fid : bean.getClass().getDeclaredFields()) {
// ํ๋๋ค ์ค์, resource๋ ์ด๋
ธํ
์ด์
๊ฐ์ง๊ณ ์๋ค๋ฉด ๋ฐ์ ์คํ
if(fid.getAnnotation(Resource.class) != null){ // by name
try {
//field.set(ํด๋น ๋ณ์๊ฐ ์ํ ๊ฐ์ฒด, ํด๋น ๋ณ์์ ๋ฃ์ ๊ฐ)
// fid.getName์ fid๊ฐ ๊ฐ์ฒด์ด๋ฏ๋ก, ํด๋น ๊ฐ์ฒด์ ํด๋์ค ๋ช
์ ๋ฐํํ๋ค.
// ๊ทธ๋ฆฌ๊ณ getBean์ด ๊ทธ ํด๋์ค๋ช
๊ณผ ๊ฐ์ Key๋ฅผ Map์์ ์ฐพ์์ ๊ทธ Key์ ํด๋นํ๋ Value๋ฅผ ๋ฐํํ๋ค.
fid.set(bean, getBean(fid.getName())); //car.engine = obj ; ๋์
์ฐ์ฐ
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
}
4. ์ค์ค๋ก ํด๋ณด๊ธฐ
๋ด์ฉ์ด ์ด๋ ค์์ ์ ๋ณด๊ณ ์ ์ง๋ ๋ชป ํ๋ค. ๊ทธ ๋์ @AutoWired @Resource๋ค์ toggle ์์ผ ๋ณด์๋ค.