IoC

James_·2022년 5월 16일
0

IoC?

스프링에서는 일반적인 Java객체를 new로 생성하여 개발자가 관리하는 것이 아닌 Spring Container에게 위임하는 것.
개발자 -> 프레임워크에게 제어의 객체관리의 권한이 넘어갔음으로 "제어의 역전"으로 불린다.

DI

의존성 주입이라고도 한다. 종속성을 내부에서 생성하는게 아니라 외부에서 주입해준다.

장점

  • 의존성으로부터 격리시켜 코드 테스트 용이
  • DI를 통하여, 불가능한 상황을 Mock과 같은 것을 통해, 안정적으로 테스트 가능
  • 코드를 확장하거나 변경할때 영향을 최소화 한다.(추상화)
  • 순환참조를 막을 수 있다.

Spring에서 Ioc해보기

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(키네임,클래스);로 자유롭게 쓸 수 있게 되었다.

profile
Android 개발자

0개의 댓글