728x90

1. 다형성

Car car = (Car) getObject("car"); 
Engine engine = (Engine) getObject("engine");
static Object getObject(String key) throws Exception {  
  Properties p = new Properties(); 
  p.load( new FileReader("config.txt") ); 
 
  Class clazz = Class.forName( p.getProperty(key) ); // 설계도면을 얻어서 
  return clazz.newInstance(); 객체를 생성해서 반환 
}

config.txt  

car = com.xxx.ch2.SportsCar 
engine = com.ddd.ch2.Engine

[ Properties 클래스 ]

  • MAP 계열의 컬렉션 프레임워크와 비슷하게 동작하는 파일
  • "Key = Value" 형태로 된 "파일이름.properties" 파일 또는 Xml 파일
  • key를 주면 Value를 반환하는 기능을 가짐
  • DB의 연결정보 등을 저장해두는 용도로 많이 쓰임

 

2. 객체컨테이너(저장소)

class AppContext {
    Map map;

    AppContext() {
        try {
            Properties p = new Properties();
            p.load(new FileReader("config.txt"));

            map = new HashMap(p);
            for (Object key : map.keySet()) {
                Class clazz = Class.forName((String) map.get(key));
                map.put(key, clazz.newInstance());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    Object getBean (String key ){
        return map.get(key);
    } 
}

public class Main3 {
    public static void main( String[] args ) throws Exception {
        AppContext ac = new AppContext();
        Car car = (Car) ac.getBean("car");
        Engine engine = (Engine) ac.getBean("engine");
    }
}

config.txt  

car = com.xxx.ch2.SportsCar 
engine = com.ddd.ch2.Engine

 

3. 자동 객체 등록하기 ( @Component )

https://mvnrepository.com/search?q=guava 

pom.xml

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.1-jre</version>
</dependency>
import org.springframework.stereotype.Component;
package com.test.ch3;

import com.google.common.reflect.ClassPath;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@Component class Bus{}
@Component class Truck{}

class AppContext {
    Map map;

    AppContext() {
        map = new HashMap();
        doComponentScan();
    }

    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.test.ch3");
            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);
    }
}

public class Main3 {
    public static void main( String[] args ) throws Exception {
        AppContext ac = new AppContext();
        Truck truck = (Truck) ac.getBean("truck");
        Bus bus = (Bus) ac.getBean("bus");
        System.out.println("truck = " + truck);
        System.out.println("bus = " + bus);
    }
}

truck 에 @Component를 제거하면 위처럼 나온다.

 

4. 객체 찾기 ( by name , by Type )

@Component class Bus{}
@Component class Truck{}


class AppContext {
    Map map;

    AppContext() {
        map = new HashMap();
        doComponentScan();
    }

    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.test.ch3");
            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 ){  // 이름으로 검색 by name
        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 Main3 {
    public static void main( String[] args ) throws Exception {
        AppContext ac = new AppContext();
        Truck truck = (Truck) ac.getBean("truck");
        Bus bus = (Bus) ac.getBean("bus");      // 이름으로 검색 by name
        Bus bus2 = (Bus) ac.getBean(Bus.class); // 클래스로 검색 by type

        System.out.println("truck = " + truck);
        System.out.println("bus = " + bus);
        System.out.println("bus2 = " + bus2);
    }
}

 

5. 객체를 자동 연결하기 ( @Autowired : by Type )

     - 타입으로 먼저 검색 , 여러개인 경우 이름으로 찾음

     - 주입받을 의존객체가 필수적이지 않을 경우 @Autowired(required = false)로 설정해서

       의존객체를 주입받지 못하더라도 빈을 생성하도록 할 수 있다.

6. 객체를 자동 연결하기 ( @Resource : by Name )

    - 아파치 톰캣 라이브러리에 존재함.

 

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

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

@Component class Engine{}
@Component class Door{}


class AppContext {
    Map map;

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

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

    private void doResource() {
        // map 에 저장된 객체의 iv 중에 @Resource 붙어 있으면
        // map 에서 iv의 타입에 맞는 객체를 찾아서 연결( 객체의 주소를 iv저젱)
        try {
            for( Object bean : map.values()){
                for(Field fid : bean.getClass().getDeclaredFields()){
                    if(fid.getAnnotation(Resource.class) != null )
                        fid.set(bean, getBean(fid.getName()));
                }
            }
        } 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.test.ch3");
            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 ){
        for( Object obj : map.values() ){
            if( clazz.isInstance(obj) ){ return obj; }
        }
        return null;
    }
}

public class Main3 {
    public static void main( String[] args ) throws Exception {
        AppContext ac = new AppContext();
        Car car = (Car) ac.getBean("car");  // 이름으로 검색
        Engine engine = (Engine) ac.getBean("engine");
        Door door = (Door) ac.getBean(Door.class); // 클래스로 검색
        
        // 수동으로 객체를 연결
        // car.engine = engine;
        // car.door = door;

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

+ Recent posts