220219_스프링 입문_스프링을 조금 더 들여다보기_IoC, DI(2)_패스트캠퍼스 챌린지 27일차
<2022년 02월 19일 _ 패스트캠퍼스 챌린지 27일차>
[스프링 입문_스프링을 조금 더 들여다보기_IoC, DI(2)]
지난강의에 이어집니다~
220218_스프링 입문_스프링을 조금 더 들여다보기_IoC, DI(1)_패스트캠퍼스 챌린지 26일차
220218_스프링 입문_스프링을 조금 더 들여다보기_IoC, DI(1)_패스트캠퍼스 챌린지 26일차 [스프링 입문_스프링을 조금 더 들여다보기_IoC, DI(1)] 1. IoC (Inversion Of Control) : 스프링에서는 일반적인 Java..
mylife4hi.red
1. IoC (Inversion Of Control)
: 스프링에서는 일반적인 Java 객체를 new로 생성하여 개발자가 관리하는 것이 아닌, Spring Container에 모두 맡긴다
: 개발자에서 -> 프레임워크로 제어의 객체 관리의 권한이 넘어 갔음 으로 '제어의 역전' 이라고 한다
2. DI (Dependency Injection)
: 의존성으로부터 격리시켜 코드 테스트에 용이함
: DI를 통해, 불가능한 상황을 Mock와 같은 기술을 통해, 안정적으로 테스트 가능
: 코드를 확장하거나 변경 할 때 영향을 최소화 함(추상화)
: 순환 참조를 막을 수 있다.
3. 실습_IoC
(1) File > New > Project > Spring Initializr
: Artifact(spring-ioc), Language(Java), Type(Gradle), Java(11), Packaging(Jar) Next 클릭
: Web(Spring Web) 체크 Finish 클릭
(2) 이전 프로젝트에서 Main을 제외하고 복사해 옵시다
package com.example.springioc;
public interface IEncoder {
String encode(String message);
}
package com.example.springioc;
public class Encoder implements IEncoder{
private IEncoder iEncoder;
public Encoder(IEncoder iEncoder){
this.iEncoder = iEncoder;
}
public String encode(String message){
return iEncoder.encode(message);
}
}
package com.example.springioc;
import java.util.Base64;
public class Base64Encoder implements IEncoder{
public String encode(String message){
return Base64.getEncoder().encodeToString(message.getBytes());
}
}
package com.example.springioc;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class UrlEncoder implements IEncoder{
public String encode(String message){
try {
return URLEncoder.encode(message, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
}
: DI를 설명하며 작성한 클래스들, 개발자가 직접 만든 객체를 주입해주었다.
: IoC는 Spring container가 이런 것들을 직접 생성해주므로, 생명주기까지 모두 가져가준다
(3) Base64Encoder, UrlEncoder 를 객체로 관리해달라는 요청을 해봅시다~
@Component
클래스 명 위에 @Component 어노테이션을 붙여줍니다
그럼 다음과 같이 Spring 이 실행이 될때 @Component 어노테이션이 붙은 객체를 singleton 형태로 만들어 Bean으로 관리를 하게 된다
그럼 이 것들을 어떻게 꺼내서 쓸까요?
(4) ApplicationContextProvider 클래스를 추가하고, ApplicationContextAware를 상속해줍니다
package com.example.springioc;
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;
//외부로부터 ApplicationContext를 주입 받는데, Spring이 자동으로 주입해준다!
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getContext(){
return context;
}
}
: Spring 어플리케이션이 실행이 되어 ApplicationContextProvider 를 만들 때, set 메소드에 ApplicationContext를 주입 해주고, context에 해당 applicationContext를 할당하면, 우리는 getContext()로 가져다 쓰면 된다.
(5) 그럼 Main문을 작성 해보자
package com.example.springioc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class SpringIocApplication {
public static void main(String[] args) {
//Spring 어플리케이션의 실행
SpringApplication.run(SpringIocApplication.class, args);
ApplicationContext context = ApplicationContextProvider.getContext();
//주입을 IoC로 하므로 객체 관리를 new 로 하지 않는다
Base64Encoder base64Encoder = context.getBean(Base64Encoder.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);
}
}
실행결과:
d3d3Lm5hdmVyLmNvbS9ib29rcy9pdD9wYWdlPTEwJnNpemU9MjAmbmFtZT1zcHJpbmctYm9vdA==
(6) Main 문을 추가 작성해줍시다
UrlEncoder urlEncoder = context.getBean(UrlEncoder.class);
result = urlEncoder.encode(url);
System.out.println(result);
전체 Main 코드
package com.example.springioc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class SpringIocApplication {
public static void main(String[] args) {
//Spring 어플리케이션의 실행
SpringApplication.run(SpringIocApplication.class, args);
ApplicationContext context = ApplicationContextProvider.getContext();
String url = "www.naver.com/books/it?page=10&size=20&name=spring-boot";
//주입을 IoC로 하므로 객체 관리를 new 로 하지 않는다
Base64Encoder base64Encoder = context.getBean(Base64Encoder.class);
Encoder encoder = new Encoder(base64Encoder);
String result = encoder.encode(url);
System.out.println(result);
UrlEncoder urlEncoder = context.getBean(UrlEncoder.class);
result = urlEncoder.encode(url);
System.out.println(result);
}
}
결과:
d3d3Lm5hdmVyLmNvbS9ib29rcy9pdD9wYWdlPTEwJnNpemU9MjAmbmFtZT1zcHJpbmctYm9vdA==
www.naver.com%2Fbooks%2Fit%3Fpage%3D10%26size%3D20%26name%3Dspring-boot
둘다 모두 스프링에서 관리되도록 제어의 역전이 일어났다!! IoC!
그렇다면 Encoder도 스프링에서 관리해주도록 해보면 어떨까?
(7) Encoder에 @Component 를 붙여준다!
@Component
public class Encoder implements IEncoder{
: 생성자의 파라미터에서 IEncoder가 UrlEncoder인지 Base64Encoder인지 인식하지 못해 오류가 발생한다.
public Encoder(@Qualifier("urlEncoder") IEncoder iEncoder){
this.iEncoder = iEncoder;
}
public Encoder(@Qualifier("base64Encoder") IEncoder iEncoder){
this.iEncoder = iEncoder;
}
: 생성자의 파라미터 앞에 @Qualifier 에 Bean의 이름을 넣어주어 지정하면, 오류가 발생하지 않는다~
(8) Main문 추가 작성
//기본 할당한 것으로 할당이 된다~!!
Encoder defaultEncoder = context.getBean(Encoder.class);;
result = defaultEncoder.encode(url);
System.out.println(result);
결과:
d3d3Lm5hdmVyLmNvbS9ib29rcy9pdD9wYWdlPTEwJnNpemU9MjAmbmFtZT1zcHJpbmctYm9vdA==
--> 이제 코드에서 new로 생성하는 부분을 찾을 수 없다.
--> 스프링에서 모든 생명주기가 관리가 가능하다
두개의 Encoder를 생성자에서 사용하고 싶은데 어떻게 할까?
(9) Encoder 소스 변경
: Component 어노테이션, Qualifier 어노테이션 제거
--> Appconfig 클래스 추가
package com.example.springioc;
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 SpringIocApplication {
public static void main(String[] args) {
//Spring 어플리케이션의 실행
SpringApplication.run(SpringIocApplication.class, args);
ApplicationContext context = ApplicationContextProvider.getContext();
String url = "www.naver.com/books/it?page=10&size=20&name=spring-boot";
//기본 할당한 것으로 할당이 된다~!!
Encoder encoder = context.getBean("base64Encode" ,Encoder.class);;
String result = encoder.encode(url);
System.out.println(result);
encoder = context.getBean("urlEncode" ,Encoder.class);;
result = encoder.encode(url);
System.out.println(result);
}
}
@Configuration
class AppConfig{
@Bean("base64Encode")
public Encoder encoder(Base64Encoder base64Encoder){
return new Encoder(base64Encoder);
}
@Bean("urlEncode")
public Encoder encoder(UrlEncoder urlEncoder){
return new Encoder(urlEncoder);
}
}
결과:
d3d3Lm5hdmVyLmNvbS9ib29rcy9pdD9wYWdlPTEwJnNpemU9MjAmbmFtZT1zcHJpbmctYm9vdA==
www.naver.com%2Fbooks%2Fit%3Fpage%3D10%26size%3D20%26name%3Dspring-boot
정리:
- 주입 받기 위해서는, 생성자 or set메소드 or auto wired나 injector등의 어노테이션을 이용한다
- 스프링에서 객체를 직접 관리하는 것 : Bean
- Bean들이 관리되고 있는 장소 : Spring container
- 스프링에서 이러한 객체의 제어 권한을 가져갔다 : 제어의 역전! = IoC
27일차 강의 완료~
패스트캠퍼스 [직장인 실무교육]
프로그래밍, 영상편집, UX/UI, 마케팅, 데이터 분석, 엑셀강의, The RED, 국비지원, 기업교육, 서비스 제공.
fastcampus.co.kr
본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.
'개발새발 > Spring' 카테고리의 다른 글
220221_스프링 입문_스프링을 조금 더 들여다보기_AOP 실무 사례 알아보기(1)_패스트캠퍼스 챌린지 29일차 (0) | 2022.02.21 |
---|---|
220220_스프링 입문_스프링을 조금 더 들여다보기_AOP_패스트캠퍼스 챌린지 28일차 (0) | 2022.02.20 |
220218_스프링 입문_스프링을 조금 더 들여다보기_IoC, DI(1)_패스트캠퍼스 챌린지 26일차 (0) | 2022.02.18 |
220217_스프링 입문_스프링을 조금 더 들여다보기_스프링의 핵심_패스트캠퍼스 챌린지 25일차 (0) | 2022.02.17 |
220216_스프링 입문_스프링 부트 시작하기_Object Mapper 및 모범사례_패스트캠퍼스 챌린지 24일차 (0) | 2022.02.16 |