스프링에서는 일반적인 Java객체를 new로 생성하여 개발자가 관리하는 것이 아닌 Spring Container에게 위임하는 것.
개발자 -> 프레임워크에게 제어의 객체관리의 권한이 넘어갔음으로 "제어의 역전"으로 불린다.
의존성 주입이라고도 한다. 종속성을 내부에서 생성하는게 아니라 외부에서 주입해준다.
ApplicationContextProvider.java
@Component
public class ApplicationContextProvider implements ApplicationContextAware {
public static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getContext(){
return context;
}
}
Compoenent 어노테이션을 붙여주고 context를 바로 쓸 수 있게끔 static으로 선언해준다.
인코더를 예시로 IoC를 할 예정이므로 우선 인코더 클래스,인터페이스를 정의하겠다.
IEncoder.java
public interface IEncoder {
public String encode(String message);
}
Base64Encoder.java
@Component
public class Base64Encoder implements IEncoder{
@Override
public String encode(String message) {
return Base64.getEncoder().encodeToString(message.getBytes());
}
}
UrlEncoder.java
@Component
public class UrlEncoder implements IEncoder{
@Override
public String encode(String message) {
try{
return URLEncoder.encode(message,"UTF-8");
}catch (UnsupportedEncodingException e){
e.printStackTrace();
return null;
}
}
}
context.getBean(class)로 encoder들을 불러올 수 있는 것을 확인할 수 있다.
@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 = new Encoder(base64Encoder);
String url = "www.naver.com/books/it?page=10&size=20&name=spring-boot";
String result = encoder.encode(url);
System.out.println(result);
encoder.setIEncoder(urlEncoder);
result = encoder.encode(url);
System.out.println(result);
}
}
출력
d3d3Lm5hdmVyLmNvbS9ib29rcy9pdD9wYWdlPTEwJnNpemU9MjAmbmFtZT1zcHJpbmctYm9vdA==
www.naver.com%2Fbooks%2Fit%3Fpage%3D10%26size%3D20%26name%3Dspring-boot
이제 인코더도 주입을 받아보자
하지만 IEncoder를 implements한 클래스가 하나가 아니기 때문에 스프링 컨테이너에서 어떤 객체를 주입할지 모르게된다.
@Component
public class Encoder{
...
// url? base64?
public Encoder(IEncoder iEncoder){
this.iEncoder = iEncoder;
}
...
}
Qualifier 어노테이션을 이용해 어떤 객체를 주입 받을건지 명시해줄 수 있다.
보통은 @Componenet("ExampleClass")를 안해주게 되면 기본적으로 exapleClass로 사용할 수 있다.
@Component
public class Encoder{
...
// base64인코더 클래스를 주입하겠다.
public Encoder(@Qualifier("base64Encoder") IEncoder iEncoder){
this.iEncoder = iEncoder;
}
...
}
main으로 가서 실행시켜보면
public static void main(String[] args) {
SpringApplication.run(IocApplication.class, args);
ApplicationContext context = ApplicationContextProvider.getContext();
String url = "www.naver.com/books/it?
Encoder encoder = context.getBean(Encoder.class);
String res = encoder.encode(url);
System.out.println(res);
출력
d3d3Lm5hdmVyLmNvbS9ib29rcy9pdD9wYWdlPTEwJnNpemU9MjAmbmFtZT1zcHJpbmctYm9vdA==
base64로 잘 출력되는 것을 확인할 수 있다.
여기서 또 인코더를 두가지를 같이 사용하고 싶은 상황이 생기게 된다.
그렇게 하기 위해선, Encoder 클래스에 Component,Qualifer 어노테이션을 제거해준 후,
AppConfig.java를 만들어준다.
@Configuration
class AppConfig{
@Bean("base64Encode")
//키네임 충동을 방지 ..Encoder -> ..Encode
public Encoder encoder(Base64Encoder base64Encoder){
return new Encoder(base64Encoder);
}
@Bean("urlEncode") // 전에 만들어놓았던 urlEncoder 키네임 충동을 방지해주기 위해 encode로 작성함.
public Encoder encoder(UrlEncoder urlEncoder){
return new Encoder(urlEncoder);
}
}
Application main에서
String url = "www.naver.com/books/it?page=10&size=20&name=spring-boot";
Encoder encoder = context.getBean("urlEncode",Encoder.class);
String res = encoder.encode(url);
System.out.println(res);
context.getBean(키네임,클래스);로 자유롭게 쓸 수 있게 되었다.