설정 파일이나 어노테이션을 통해 객체 간의 의존 관계를 설정하여 개발자가 직접 객체 간의 의존 관계를 생성할 필요가 없다.
-> 의존정 주입 = 직접적인 연결을 깨부수는 것 -> 결합도를 낮춤
-> 지난 과정에서(mybatis) DAO - service - Controller 순으로 연결되어 서로 객체 간의 직접 연결로 의존 관계가 높았다.
하지만 SPRING 프렘임워크에서는 객체 간의 직접연결을 깨부수고 어떠한 빈 공간(Spring container)에 객체를 저장해놓고 필요할 때 꺼내서 쓸 수 있도록 만들어 객체 간 결합도를 낮춘다.
-> 이번 시간에는 3개의 과정을 통해 객체 연결하는 방법을 알아보도록 하자




package com.kh.di;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
// hello.properties(부가정보, meta-data)의 내용을 읽어 Hello 객체를 생성하여 return
public class HelloFactory {
private Hello hello;
private Properties properties;
// 싱글톤 패턴 작성
private static HelloFactory helloFactory;
private HelloFactory() {}
public synchronized static HelloFactory getInstance() {
//synchronized : 동기화 하는 역할 (Factory(공장) 이 처리가 이루어지는 동안 나머지 것들의 접근을 막는 역할)
if(helloFactory == null) {
helloFactory = new HelloFactory();
}
return helloFactory;
}
// properties file을 추상화, 캡슐화한 java.util.properties 객체 생성
// congigResource는 properties 파일의 경로나 위치를 나타냄
public void setConfigResource(String configResource) {
FileInputStream fis = null;
try { // FileInputStream 통해 congigResource에 지정된 경로의 properties파일을 연다.
fis = new FileInputStream(configResource);
properties = new Properties();
// Properties 객체에 FileInputStream 통해 읽은 프롶티 파일을 로드(저장)한다.
// 이 메소드는 파일에서 읽은 내용을 키=값 의 형태로 properties 객체에 저장
-> 나중에 .getProperty(key)통해 값을 가져올 수 있음
properties.load(fis);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fis!=null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
// name에 해당하는 객체 생성
private void newInstanceHello(String name) {
// 키= 값 형태로 properties객체에 저장했기 때문에 .getProperty(name)통해 해당 값 가져올 수 잇음
String className = properties.getProperty(name).trim();
// trim : 앞 , 뒤 여백을 포함하고 잇는 것을 제거
System.out.println("hello.properties에서 추출한 className: " + className);
try {
Class cls = Class.forName(className);
Object obj = cls.newInstance();
// .newInstance() : 주어진 클래스의 기본 생성자 호출하여 새로운 객체 생성
ex. "com.kh.di.hello" 클래스의 기본 생성자 호출 하여
"Hello" 클래스의 인스턴스가 생성됨
if(obj instanceof Hello) { // 만든 클래스가 진짜 Hello 인지 확인
this.hello = (Hello) obj;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch(Exception e) {
e.printStackTrace();
}
}
// Hello 객체 생성하는 new InstanceHello() 호출 및 Hello객체를 return
public Hello getBean(String name) {
this.newInstanceHello(name);
return hello;
}
// getBean 메소드는 주어진 이름에 해당하는 클래스 생성하고 생성된 클래스의 인스턴스를 반환함으로써
// 특정 이름에 대응하는 빈(Bean)을 반환하는 역할
}

- HelloFactory 대신 BeanFactory 사용
- BeanFactory는 이미 만들어져 있기 때문에 우리가 따로 만들 필요가 없다.
- BeanFactory : spring loC 컨테이너의 기본 인터페이스(빈의 생성, 의존성 주입, 초기화등의 기능을 함)
2번째 방법에서는 Hello객체를 properties 파일에 저장했지만 이번엔 xml 파일에 저장해준다.

BeanFactory 사용하여 객체 연결
public class HelloTestApp3UsingSpring {
public static void main(String[] args) {
//1. BeanFactory 생성.. 주문서는 공장에서 미리 받아서 읽기
// 주문서 만들기 : 빈(Bean)설정 문서
System.out.println("1. BeanFactory 생성..");
//이젠 HelloFactory 만들 필요 없이 만들어져 잇는 BeanFactory 이용
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("src/main/resources/config/hello.xml"));
//1. "src/main/resources/config/hello.xml" 경로에 있는 Bean 설정 문서인 hello.xml을 읽어오기 위해 FileSystemResource를 생성
//2. FileSystemResource 객체를 XmlBeanFactory 생성자에 전달하여 설정 파일을 로드
//3. XmlBeanFactory는 설정 파일을 읽어와서 빈(Bean) 객체 생성하여 변수 factory에 저장
// 2. getBean()으로 빈을 받아와서 printMessage() 호출
System.out.println("2.getBean() 클라이언트 호출...");
Hello hello = (Hello)factory.getBean("hello"); //"hello" 는 hello.xml에서 설정한 id
hello.printMessage();
}
}