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);
}
}
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