변경에 유리한 코드(1) - 다형성, factory method
class Car{}
class SportsCar extends Car{}
class Truck extends Car{}
Car car = getCar();
static Car getCar(){
return new SportsCar();
}
static Car getCar(){
return new Truck();
}
변경에 유리한 코드(2) - Map, 외부 파일
Car car = getCar();
static Car getCar() throws Exception {
// config.txt 를 읽어서 Properties 에 저장
Properties p = new Properties(); // Map(Object, Object), Properties(Stirng, String)
p.load(new FileReader("config.txt");
// 클래스 객체(설계도)를 얻어서
Class clazz = Class.forname(p.getProperty("car"));
return (Car)clazz.newInstance(); // 객체를 생성해서 반환
}
package com.fastcampus.ch3.diCopy1;
import java.io.FileReader;
import java.util.Properties;
class Car {}
class SportsCar extends Car {}
class Truck extends Car {}
class Engine {}
public class Main1 {
public static void main(String[] args) throws Exception{
Car car = (Car)getObject("car");
Engine engine = (Engine) getObject("engine");
System.out.println("car = " + car);
System.out.println("engine = " + 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 (Object)clazz.newInstance();
}
// static Car getCar() throws Exception {
// Properties p = new Properties();
// p.load(new FileReader("config.txt"));
//
// Class clazz = Class.forName(p.getProperty("car"));
//
// return (Car)clazz.newInstance();
// }
}
객체 컨테이너(ApplicationContext) 만들기
package com.fastcampus.ch3.diCopy2;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
class Car {
}
class SportsCar extends Car {
}
class Truck extends Car {
}
class Engine {
}
class AppContext {
Map map; // 객체 저장소
AppContext() {
map = new HashMap<>();
map.put("car", new SportsCar());
map.put("engine", new Engine());
}
Object getBean(String key) {
return map.get(key);
}
}
public class Main2 {
public static void main(String[] args) throws Exception {
AppContext ac = new AppContext();
Car car = (Car) ac.getBean("car");
Engine engine = (Engine) ac.getBean("engine");
System.out.println("car = " + car);
System.out.println("engine = " + engine);
}
}
car = com.fastcampus.ch3.diCopy2.SportsCar@6f75e721
engine = com.fastcampus.ch3.diCopy2.Engine@69222c14
package com.fastcampus.ch3.diCopy2;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
class Car {
}
class SportsCar extends Car {
}
class Truck extends Car {
}
class Engine {
}
class AppContext {
Map map; // 객체 저장소
AppContext() {
try {
Properties p = new Properties();
p.load(new FileReader("config.txt"));
// properties 에 있는 내용을 map 에 저장
map = new HashMap<>(p);
// 반복문으로 클래스 이름을 얻고 객체를 생성해서 map 에 저장
for(Object key : map.keySet()) {
Class clazz = Class.forName((String)map.get(key));
map.put(key, clazz.newInstance());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Object getBean(String key) {
return map.get(key);
}
}
public class Main2 {
public static void main(String[] args) throws Exception {
AppContext ac = new AppContext();
Car car = (Car) ac.getBean("car");
Engine engine = (Engine) ac.getBean("engine");
System.out.println("car = " + car);
System.out.println("engine = " + engine);
}
}
car = com.fastcampus.ch3.diCopy2.SportsCar@3fb4f649
engine = com.fastcampus.ch3.diCopy2.Engine@33833882
자동 객체 등록하기 - Component Scanning
@Component 어노테이션 사용해서 등록하기
package com.fastcampus.ch3.diCopy3;
import org.springframework.stereotype.Component;
import java.awt.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.springframework.util.StringUtils;
import com.google.common.reflect.ClassPath;
@Component
class Car {
}
@Component
class SportsCar extends Car {
}
@Component
class Truck extends Car {
}
@Component
class Engine {
}
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.fastcampus.ch3.diCopy3");
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();
Car car = (Car) ac.getBean("car");
Engine engine = (Engine) ac.getBean("engine");
System.out.println("car = " + car);
System.out.println("engine = " + engine);
}
}
객체 찾기 - by name, by type
package com.fastcampus.ch3.diCopy3;
import org.springframework.stereotype.Component;
import java.awt.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.springframework.util.StringUtils;
import com.google.common.reflect.ClassPath;
@Component
class Car {
}
@Component
class SportsCar extends Car {
}
@Component
class Truck extends Car {
}
@Component
class Engine {
}
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.fastcampus.ch3.diCopy3");
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"); // byName 으로 객체를 검색
Car car2 = (Car) ac.getBean(Car.class); // byType 으로 객체를 검색
Engine engine = (Engine) ac.getBean("engine");
System.out.println("car = " + car);
System.out.println("engine = " + engine);
}
}
객체를 자동 연결하기 - @Autowired (byType)
package com.fastcampus.ch3.diCopy4;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.springframework.util.StringUtils;
import com.google.common.reflect.ClassPath;
@Component
class Car {
@Autowired Engine engine;
@Autowired Door door;
@Override
public String toString() {
return "Car [engine=" + engine + ", door=" + door + "]";
}
}
@Component
class SportsCar extends Car {
}
@Component
class Truck extends Car {
}
@Component
class Engine {
}
@Component
class Door {
}
class AppContext {
Map map; // 객체 저장소
AppContext() {
map = new HashMap();
doComponentScan();
doAutowired();
}
private void doAutowired() {
try {
// map 에 저장된 객체의 iv 중에 @Autowired 가 붙어 있으면
// map 에서 iv 의 타입에 맞는 객체를 찾아서 연결(객체의 주소를 iv 저장)
for (Object bean : map.values()) {
for(Field fld : bean.getClass().getDeclaredFields()) {
if(fld.getAnnotation(Autowired.class)!=null) // byType {
fld.set(bean, getBean(fld.getType())); // car.engine = obj;
}
}
} catch (Exception 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) {
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"); // byName 으로 객체를 검색
Engine engine = (Engine) ac.getBean("engine");
Door door = (Door) ac.getBean(Door.class); // byType 으로 객체를 검색
// 수동으로 객체를 연결
// car.engine =engine;
// car.door= door;
System.out.println("car = " + car);
System.out.println("door = " + door);
}
}
car = Car [engine=com.fastcampus.ch3.diCopy4.Engine@262b2c86, door=com.fastcampus.ch3.diCopy4.Door@371a67ec]
door = com.fastcampus.ch3.diCopy4.Door@371a67ec
객체를 자동 연결하기 - @Resource (byName)
package com.fastcampus.ch3.diCopy4;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import org.springframework.util.StringUtils;
import com.google.common.reflect.ClassPath;
@Component
class Car {
@Resource Engine engine;
@Resource Door door;
@Override
public String toString() {
return "Car [engine=" + engine + ", door=" + door + "]";
}
}
@Component
class SportsCar extends Car {
}
@Component
class Truck extends Car {
}
@Component
class Engine {
}
@Component
class Door {
}
class AppContext {
Map map; // 객체 저장소
AppContext() {
map = new HashMap();
doComponentScan();
doAutowired();
doResource();
}
private void doResource() {
try {
// map 에 저장된 객체의 iv 중에 @Resource 가 붙어 있으면
// map 에서 iv 의 타입에 맞는 객체를 찾아서 연결(객체의 주소를 iv 저장)
for (Object bean : map.values()) {
for(Field fld : bean.getClass().getDeclaredFields()) {
if(fld.getAnnotation(Resource.class)!=null) // buName {
fld.set(bean, getBean(fld.getName())); // car.engine = obj;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void doAutowired() {
try {
// map 에 저장된 객체의 iv 중에 @Autowired 가 붙어 있으면
// map 에서 iv 의 타입에 맞는 객체를 찾아서 연결(객체의 주소를 iv 저장)
for (Object bean : map.values()) {
for(Field fld : bean.getClass().getDeclaredFields()) {
if(fld.getAnnotation(Autowired.class)!=null) // byType {
fld.set(bean, getBean(fld.getType())); // car.engine = obj;
}
}
} catch (Exception 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) {
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"); // byName 으로 객체를 검색
Engine engine = (Engine) ac.getBean("engine");
Door door = (Door) ac.getBean(Door.class); // byType 으로 객체를 검색
// 수동으로 객체를 연결
// car.engine =engine;
// car.door= door;
System.out.println("car = " + car);
System.out.println("door = " + door);
}
}
car = Car [engine=com.fastcampus.ch3.diCopy4.Engine@6fb0d3ed, door=com.fastcampus.ch3.diCopy4.Door@6dde5c8c]
door = com.fastcampus.ch3.diCopy4.Door@6dde5c8c
'Spring > Ch3. Spring DI, AOP' 카테고리의 다른 글
Spring - AOP (0) | 2022.09.30 |
---|---|
Spring - Transaction (0) | 2022.09.29 |
Spring - Spring DI(1) (0) | 2022.09.13 |
Ch3-3_Spring DI 활용하기 - 이론 (0) | 2022.02.08 |
Ch3-2_Spring DI 흉내내기(2) (0) | 2022.02.07 |