DI란?
DI는 Dependency Injection의 줄임말로서 의존성 주입이라고도 부른다. 스프링은 기본적으로 DI를 기반으로 동작하기 때문에 DI에 대한 이해가 필수이다.
여기서 말하는 의존(Dependency)이란 한 클래스에서 다른 기능을 실행하기 위해 다른 클래스(또는 타입)를 필요로 할 때 이를 의존한다고 말한다.
public class FileEncryptor {
// 의존 객체를 필드(encryptor 필드)로 정의
private Encryptor encryptor = new Encryptor();
public void encrypt(File src, File target) throws IOException {
// 의존 객체를 로컬 변수(is, out 변수)로 정의
try(FileInputStream is = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(target)) {
byte[] data = new byte[512];
int len = -1;
while((len = is.read(data)) != -1) {
encryptor.encrypt(data, 0, len);
out.write(data, 0, len);
}
}
}
}
위 코드에서 FileEncryptor 클래스는 Encryptor, FileInputStream, FileOutputStream 클래스에 의존하고 있다. 그런데 이렇게 의존 객체를 필드나 로컬 변수로 직접 생성하는 방식은 큰 단점이 있다. 만약 요구사항의 변화로 Encryptor 클래스의 하위 클래스인 FastEncryptor 클래스를 사용해야 하는 상황이 발생했다면 Encryptor 클래스를 찾아서 전부 변경해야 될 것이다.
DI를 사용하는 방식의 코드 : 의존 객체를 외부에서 조립함
의존 객체를 직접 생성하는 방식과 달리 DI는 의존 객체를 외부로부터 전달받는 구현 방식이다. 여기에는 크게 두 가지 방식이 있는데, 바로 생성자 방식과 프로퍼티 설정 방식이다.
public class FileEncryptor {
private Encryptor encryptor;
// 생성자를 통해서 의존 객체를 전달
public FileEncryptor(Encryptor encryptor) {
this.encryptor = encryptor;
}
// set 메서드를 통해서 의존 객체를 전달
public void setEncryptor(Encryptor encryptor) {
this.encryptor = encryptor;
}
// 이하 생략
...
}
프로퍼티 설정 방식은 setPropertyName() 형식의 메서드를 주로 사용한다. 위 코드에서 메서드 이름이 setEncryptor()인 경우 프로퍼티 이름은 set 접두어를 빼고 첫 글자를 소문자로 바꾼 encryptor가 된다.
스프링은 객체를 생성하고 연결해주는 DI 컨테이너
다음 코드를 보자.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="mvnBuildRunner" class="[패키지경로].MavenBuildRunner">
<property name="mavenPath">
<value>c:\maven-3.8.4</value>
</property>
</bean>
<bean id="sampleProject" class="[패키지경로].Project">
<property name="srcDirs">
<list>
<value>src/</value>
<value>srcResources/</value>
</list>
</property>
<property name="binDir" value="bin/" />
<property name="buildRunner">
<ref bean="mvnBuildRunner" />
</property>
</bean>
</beans>
public interface BuildRunner {
void build(List<String> srcDirs, String binDir);
}
public class MavenBuildRunner implements BuildRunner {
private String mavenPath;
@Override
public void build(List<String> srcDirs, String binDir) {
String info = "메이븐 경로: " + mavenPath + "\n";
for (String srcDir : srcDirs) {
info += "소스 경로: " + srcDir + "\n";
}
info += "클래스파일 경로: " + binDir + "\n";
System.out.printf("MavenBuildRunner.build() 실행\n%s", info);
}
public void setMavenPath(String mavenPath) {
this.mavenPath = mavenPath;
}
}
public class Project {
private List<String> srcDirs;
private String binDir;
private BuildRunner buildRunner;
public void build() {
buildRunner.build(srcDirs, binDir);
}
public void setSrcDirs(List<String> srcDirs) {
this.srcDirs = srcDirs;
}
public void setBinDir(String binDir) {
this.binDir = binDir;
}
public void setBuildRunner(BuildRunner buildRunner) {
this.buildRunner = buildRunner;
}
}
public class Main {
public static void main(String[] args) {
String configLocation = "classpath:applicationContext.xml";
AbstractApplicationContext ctx = new GenericXmlApplicationContext(configLocation);
Project project = ctx.getBean("sampleProject", Project.class);
project.build();
ctx.close();
}
}
위 코드를 간단하게 설명하자면, XML 파일에는 생성할 객체가 무엇이고, 각 객체를 어떻게 연결하는지에 대한 정보가 들어있다. 그리고 GenericXmlApplicationContext 클래스가 XML 파일에 정의된 설정 정보를 읽어와 객체(여기서는 Project 클래스)를 생성하고 각각의 객체를 연결한 뒤에 내부적으로 보관한다. 이렇게 생성한 객체를 보관하기 때문에 스프링을 객체 컨테이너(Object Container)라고도 부른다.
XML을 이용한 스프링 설정을 보면 컨테이너가 생성할 객체를 지정하기 위해 <bean> 태그를 사용하는데, 스프링 컨테이너가 생성해서 보관하는 객체를 스프링 빈(Spring Bean) 객체라고 부른다.
스프링 컨테이너는 생성한 빈 객체를 <이름, 빈 객체> 쌍으로 보관한다. 위 코드에서 getBean() 메서드를 사용할 때 첫 번째 파라미터로 문자열(여기서는 "sampleProject")을 전달했는데 이 문자열이 스프링 빈의 이름(XML <bean> 태그의 id)에 해당한다.
다음글 : https://jaedam.tistory.com/7
[Spring] 스프링 DI를 이용한 객체 생성(2)
이전 글 : https://jaedam.tistory.com/5 앞서 DI의 개념과 스프링 컨테이너 및 빈 객체를 설정하는 방식을 간략하게 살펴보았다. 이번 글에서는 스프링 컨테이너의 종류와 XML 파일의 각 태그에 대해서 살
jaedam.tistory.com
Reference
- 웹 개발자를 위한 Spring 4.0 프로그래밍 (최범균 저)
'Spring' 카테고리의 다른 글
| [Spring] @Qualifier 어노테이션 (0) | 2022.02.11 |
|---|---|
| [Spring] @Autowired 어노테이션 (0) | 2022.02.11 |
| [Spring] 자바 설정 빈 객체 생성 방법 (0) | 2022.02.10 |
| [Spring] 스프링 DI를 이용한 객체 생성(3) (0) | 2022.02.10 |
| [Spring] 스프링 DI를 이용한 객체 생성(2) (0) | 2022.02.09 |