3-3 Spring DI 흉내내기(3)

서현우·2022년 5월 17일
0

스프링의정석

목록 보기
34/85

4. 객체 찾기 - by Name, by Type

AppContext ac = new AppContext();
Car car = (Car)ac.getBean("car"); //이름(id)으로 찾기
Car ca2 = (Car)ac.getBean("Car.class"); //타입을 찾기

Object getBean(String id) { //이름으로 찾기
	return map.get(id);
}

Object getBean(Class clazz) { //타입으로 찾기
	for(Object obj : map.values()) {
		if(clazz.isinstance(obj)) //obj instanceof clazz
			return obj;
	}
	return null;
}

5. 객체를 자동 연결 하기(1) - @Autowired

1. 수동 연결

AppContext ac = new AppContext(); //저장소 만듬
Car car = (Car)ac.getBean("car");
Engine engine = (Engine)ac.getBean("engine");
Door door = (Door)ac.getBean("door");

car.engine = engine;
car.door = door;

class Car {
	Engine engine;
	Door door;
}

2. 자동 연결

@Autowired
맵을 뒤져서 각 타입에 맞는 객체주소를 찾아서 참조변수에 대입.
by Type, Key값을 찾음

class Car {
	@Autowired Engine engine;
	@Autowired Door door;
}

6. 객체를 자동 연결 하기(2) - @Resource

by Name, instanceof로 Value값을 찾음.
타입의 첫글자를 소문자로 바꿔서 찾음.
@Resource(name="engine2")을 써서 찾을 수도 있음.

Class Car {
	@Resource Engine engine;
	@Resource Door door;
}
Class Car {
	@Reousrce(name="engine2") Engine engine;
	@Resource Door door;
}

Main4.java

package com.fastcampus.ch3.diCopy4;

import com.google.common.reflect.ClassPath;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@Component class Car {
    @Resource
    Engine engine;
//    @Resource
    Door door;

    @Override
    public String toString() {
        return "Car{" +
                "engine=" + engine +
                ", door=" + door +
                '}';
    }
}

@Component class Truck extends Car {}
@Component class SportsCar extends Car{}
@Component
class Engine {}
@Component class Door {}

class AppContext {
    Map map; //객체 저장소

    AppContext(){
        map = new HashMap();
        doComponentScan();
        doAutowired();
        doResource();

    }

    private void doResource() {
        //map에 저장된 객체의 iv중에 @Resource가 붙어 있으면
        //map에서 iv의 타입에 맞는 객체를 찾아서 연결(객체의 주소를 iv에 저장)
        try {
            for(Object bean : map.values()){
                for(Field fld : bean.getClass().getDeclaredFields()){
                    if(fld.getAnnotation(Resource.class)!=null) //byName
                        fld.set(bean, getBean(fld.getName())); //car.engine = obj;
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private void doAutowired() {
        //map에 저장된 객체의 iv중에 @Autowired가 붙어 있으면
        //map에서 iv의 타입에 맞는 객체를 찾아서 연결(객체의 주소를 iv에 저장)
        try {
            for(Object bean : map.values()){
                for(Field fld : bean.getClass().getDeclaredFields()){
                    if(fld.getAnnotation(Autowired.class)!=null)
                        fld.set(bean, getBean(fld.getType())); //car.engine = obj;
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private void doComponentScan() {
        try {
            //1. 패키지내의 클래스 목록을 가져온다.
            //2. 반복문으로 클래스를 하나씩 읽어와서 @Component이 붙어 있는지 확인
            //3. @Component가 붙어있으면 객체를 생성해서 map에 저장
            ClassLoader classLoader = AppContext.class.getClassLoader();
            ClassPath classPath = ClassPath.from(classLoader);

            Set<ClassPath.ClassInfo> set = classPath.getTopLevelClasses("com.fastcampus.ch3.diCopy4");

            for(ClassPath.ClassInfo classInfo : set){
                Class clazz = classInfo.load();
                Component component = (Component)clazz.getAnnotation(Component.class);
                if(component != null){
                    String id = StringUtils.uncapitalize(classInfo.getSimpleName());
                    map.put(id, clazz.newInstance());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();

        }
    }

    Object getBean(String key){
        return map.get(key);
    }
    Object getBean(Class clazz){ //by Type
        for(Object obj : map.values()){
            if(clazz.isInstance(obj))
                return obj;
        }
        return null;
    }
}

public class Main4 {
    public static void main(String[] args) throws Exception {
        AppContext ac = new AppContext();
        Car car = (Car)ac.getBean("car"); //by Name으로 객체를 검색
        Engine engine = (Engine)ac.getBean("engine");
        Door door = (Door)ac.getBean(Door.class); //by Type으로 객체를 검색

          //수동을 객체를 연결
//        car.engine = engine;
//        car.door = door;


        System.out.println("car = " + car);
        System.out.println("engine = " + engine);
        System.out.println("door = " + door);


    }

}
profile
안녕하세요!!

0개의 댓글