Spring

[Spring Architecture DI] IoC

sujin7837 2022. 4. 20. 00:12
반응형

IoC 개요

DL(Dependency Lookup) : 필요한 의존성을 찾아서 넣는 것

-컨테이너가 lookup context를 통해서 필요한 Resource나 Object를 얻는 방식

-JNDI 이외의 방법을 사용한다면 JNDI 관련 코드를 오브젝트 내에서 일일히 변경해줘야 함

-Lookup 한 Object를 필요한 타입으로 Casting 해주어야 함

-Naming Exception을 처리하기 위한 로직 필요

 

DI(Dependency Injection) : 의존성을 알아서 주입해주는 것

-Object에 lookup 코드를 사용하지 않고 컨테이너가 직접 의존 구조를 Object에 설정할 수 있도록 지정해주는 방식

-Object가 컨테이너의 존재 여부를 알 필요가 없음

-Lookup 관련된 코드들이 Object 내에서 사라짐

-Setter Injection과 Constructor Inject

 

IoC의 개념

-객체 제어 방식 : 기존에는 필요한 위치에서 개발자가 필요한 객체를 생성하는 로직을 구현하였으나, IoC는 객체 생성을 Container에게 위임하여 처리함

-Loose Coupling : IoC를 사용하면 객체 간의 결합도를 떨어뜨릴 수 있다는 장점이 있음

객체 간 결합도가 높으면, 해당 클래스가 유지보수 될 때, 그 클래스와 결합된 다른 클래스도 같이 유지보수 되어야 할 가능성이 높습니다. 이를 해결하기 위한 방안을 살펴보겠습니다.

 

객체 간 강한 결합

-클래스 호출 방식
-클래스 내에 선언과 구현이 모두 되어있기 때문에 다양한 형태로 변화 불가능
-Service 구현체를 Controller에서 직접 생성하여 사용할 경우, Service를 다른 Service 코드로 교체하거나 내부 코드가 변경되면 Controller까지 수정해야 할 수도 있음
public class RedCar {

	public String rideRedCar(String color) {
		return "Car " + color;
	}
	
}
public class BlueCar {

	public String rideBlueCar(String color) {
		return "Car " + color;
	}
	
}
	public static void main(String[] args) {
    	RedCar redCar = new RedCar();
        BlueCar blueCar = new BlueCar();
		
		String choosed = redCar.rideRedCar("red");
		
		System.out.println(choosed);
	}

위 방식의 경우, blueCar로 변경할 경우나 redCar의 메소드명을 변경할 경우 main에서 많은 코드 변경이 이뤄져야 합니다.

 

1. 인터페이스 호출 방식

  • 다형성을 통해 객체 간 강한 결합을 낮춤
  • 구현 클래스 교체가 용이하여 다양한 형태로 변화 가능
  • 인터페이스 교체 시 호출 클래스도 수정해야 함

public interface Car {
	String rideCar(String color);
}
public class RedCar implements Car {
	public String rideCar(String color) {
    	return "Car " + color;
    }
}
public class BlueCar implements Car {
	public String rideCar(String color) {
    	return "Car " + color;
    }
}
	public static void main(String[] args) {
    	RedCar redCar = new RedCar();
        BlueCar blueCar = new BlueCar();
		
		String choosed = redCar.rideCar("red");
		
		System.out.println(choosed);
	}

rideCar 메서드를 Car 인터페이스를 통해 구현하였기 때문에 결합도가 낮아졌습니다. 그러나 여전히 redCar와 bluCar를 갈아끼워야 한다는 불편함이 존재합니다. 이를 해결해주기 위해 팩토리 패턴을 사용하겠습니다.

 

public class CarFactory {
	public static Car getCar(String car) {
    	if(car.equals("red")) {
        	return new RedCar();
        } else if(car.equals("blue")) {
        	return new BlueCar();
        } else {
        	return null;
        }
    }
}
	public static void main(String[] args) {
    	Car car1=CarFactory.getCar("red");
        Car car2=CarFactory.getCar("blue");
		
		System.out.println(car1);
	}

팩토리 패턴을 이용하여 입력값에 적합한 객체를 가져올 수 있게 되었습니다.

 

2. Assembler 이용

  • IoC 호출 방식
  • 팩토리 패턴의 장점을 더하여 어떠한 것에도 의존하지 않는 형태가 됨
  • 실행 시점(Runtime)에 클래스 간의 관계가 형성됨
  • 각 Service의 Life Cycle을 관리하는 Assembler를 사용
  • Spring Container가 외부조립기(Assembler) 역할을 함

	public static void main(String[] args) {
    	Car car1=CarFactory.getCar("red");
        Car car2=CarFactory.getCar("blue");
		
		System.out.println(car1);
	}

public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("com/my/car/application.xml");
//		Car car=(Car)context.getBean("red");
		Car car=context.getBean("red", RedCar.class);
		
		String car1 = car.rideCar("red");
		
		System.out.println(car1);
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

	<bean id="red" class="com.my.car.RedCar"></bean>
	<bean id="blue" class="com.my.car.BlueCar"></bean>
	
	<context:component-scan base-package="com.my.car"></context:component-scan>
</beans>

bean 설정시 default는 singleton입니다.

 

<bean id="red" class="com.my.car.RedCar" scope="prototype"></bean>

scope를 prototype으로 설정시 서로 다른 객체를 만들 수 있습니다.

반응형