개념
객체 사용을 위한 주입
의존성으로부터 격리시켜 코드 테스트에 용이
DI로 불가능한 상황을 Mock과 같은 기술을 통해 안정적인 테스트가 가능
코드 확장하거나 변경할 때 영향을 최소화(추상화)
순환참조 막을 수 있음
1) DI 개념을 사용하지 않는 경우
// Main.java
import java.io.UnsupportedEncodingException;
public class Main {
public static void main(String[] args) throws UnsupportedEncodingException {
String url = "www.naver.com/books/it?page=10&size=20&name=spring-boot";
// Base64Encoder 객체 생성
Base64Encoder base64Encoder = new Base64Encoder();
String result = base64Encoder.encode(url);
System.out.println("Base64Encoder : " + result);
// URLEncoder 객체 생성
UrlEncoder urlEncoder = new UrlEncoder();
String urlResult = urlEncoder.encode(url);
System.out.println("UrlEncoder : " + urlResult);
}
}
// Base64Encoder.java
import java.util.Base64;
public class Base64Encoder {
public String encode(String message) {
return Base64.getEncoder().encodeToString(message.getBytes());
}
}
// UrlEncoder.java
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class UrlEncoder {
public String encode(String message) throws UnsupportedEncodingException {
return URLEncoder.encode(message, "UTF-8");
}
}
실행 결과
2) DI 개념을 사용하는 경우
// Main.java
public class Main {
public static void main(String[] args) {
// Encoding을 위한 url
String url = "www.naver.com/books/it?page=10&size=20&name=spring-boot";
// DI(외부에서 주입을 받는다)
// Encoder 생성자의 매개변수를 new UrlEncoder() 로 바꾸면 해당 Encoder 주입받음
Encoder encoder = new Encoder(new Base64Encoder());
String result = encoder.encode(url);
System.out.println(result);
}
}
// Encoder.java
public class Encoder {
private IEncoder iEncoder;
public Encoder(IEncoder iEncoder) {
this.iEncoder = iEncoder;
}
public String encode(String message) {
return iEncoder.encode(message);
}
}
// IEncoder.java
public interface IEncoder {
String encode(String message);
}
// Base64Encoder.java
import java.util.Base64;
public class Base64Encoder implements IEncoder {
@Override
public String encode(String message) {
return Base64.getEncoder().encodeToString(message.getBytes());
}
}
// UrlEncoder.java
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class UrlEncoder implements IEncoder{
@Override
public String encode(String message) {
try {
return URLEncoder.encode(message, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
실행 결과
개념
스프링에서는 일반적인 Java 객체를 new로 생성하여 개발자가 관리하는 것이 아님
모든 객체의 제어 권한은 Spring Container에 있음
개발자에서 프레임워크로 제어 객체 관리의 권한이 넘어갔으므로 "제어의 역전"이라고 함
Spring Container라는 공간에 우리가 사용하고자 하는 객체가 이미 만들어져 있고, 싱글톤 형태로 관리
// IoCApplication.java
package com.example.IoC;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@SpringBootApplication
public class IoCApplication {
public static void main(String[] args) {
SpringApplication.run(IoCApplication.class, args);
ApplicationContext context = ApplicationContextProvider.getContext();
// 클래스로 찾기
// Base64Encoder base64Encoder = context.getBean(Base64Encoder.class);
// UrlEncoder urlEncoder = context.getBean(UrlEncoder.class);
// 이름으로 찾기
Encoder encoder = context.getBean("urlEncode", Encoder.class);
String url = "www.naver.com/books/it?page=10&size=20&name=spring-boot";
String result = encoder.encode(url);
System.out.println(result);
}
}
@Configuration // 한 개의 클래스에서 여러 개의 Bean을 등록할 것이라고 명시
class AppConfig {
// Base64Encoder 주입
// Bean으로 등록
@Bean("base64Encode")
public Encoder encoder(Base64Encoder base64Encoder) {
return new Encoder(base64Encoder);
}
// UrlEncoder 주입
// Bean으로 등록
@Bean("urlEncode")
public Encoder encoder(UrlEncoder urlEncoder) {
return new Encoder(urlEncoder);
}
}
package com.example.IoC;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext context;
// 여기에서 Spring이 주입해줌
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getContext() {
return context;
}
}
// Encoder.java
package com.example.IoC;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class Encoder {
private IEncoder iEncoder;
public Encoder(@Qualifier("base74Encoder") IEncoder iEncoder) {
this.iEncoder = iEncoder;
}
public void setIEncoder(IEncoder iEncoder) {
this.iEncoder = iEncoder;
}
public String encode(String message) {
return iEncoder.encode(message);
}
}
// IEncoder.java
package com.example.IoC;
public interface IEncoder {
String encode(String message);
}
// Base64Encoder.java
package com.example.IoC;
import org.springframework.stereotype.Component;
import java.util.Base64;
@Component("base74Encoder")
// Spring에게 객체로 관리해달라는 annotation, 이 객체가 Bean으로 등록됨
public class Base64Encoder implements IEncoder {
@Override
public String encode(String message) {
return Base64.getEncoder().encodeToString(message.getBytes());
}
}
// UrlEncoder.java
package com.example.IoC;
import org.springframework.stereotype.Component;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
@Component
public class UrlEncoder implements IEncoder{
@Override
public String encode(String message) {
try {
return URLEncoder.encode(message, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}
실행 결과
@Component
Spring Container에 접근해서 객체 가져오기
Bean 찾기
Base64Encoder base64Encoder = context.getBean(Base64Encoder.class);
Encoder encoder = context.getBean("urlEncode", Encoder.class);
Bean 주입받을 수 있는 곳
@Qualifier
@Configuration
개념 정리