본문 바로가기
  • 실행력이 모든걸 결정한다
Spring Series/Spring Framework

[Spring] DI와 IOC / IOC 컨테이너 설정(1) - xml

by 김코더 김주역 2020. 12. 18.
반응형

1.  DI와 IOC

1) DI(Dependency Injection, 의존성 주입)

- 의존관계는 사용할 오브젝트에 대한 레퍼런스를 외부에서 주입해줌으로써 만들어진다는 개념이다.

- 클래스 모델이나 코드에서 런타임 시점의 의존관계를 드러내지 않으려면, 인터페이스에 의존하고 있어야 한다.

- 런타임 시점의 의존관계는 컨테이너나 팩토리 같은 제3의 존재가 결정한다.

- DI를 원하는 오브젝트는 먼저 자신이 컨테이너가 관리하는 Bean이 되어야 한다.

 

2) Application Context

- IoC 방식을 따라 만들어진 Bean 팩토리의 기능과 스프링이 제공하는 애플리케이션 지원 기능을 통틀어 말한다.

- Bean 오브젝트의 생성, 관계설정 등의 제어 작업을 총괄한다.

- IoC 컨테이너, 스프링 컨테이너라고 부르기도 하고, 단순히 Bean 팩토리라고 부르기도 한다.

 

3) IOC(Inversion of Control, 제어의 역전)★

인스턴스의 생명주기에 대한 제어권을 스프링에 위임하는 것

 

 

2. IOC 컨테이너 설정 - xml 작성

IOC 컨테이너를 설정한다는 것은 특정 객체를 스프링이 관리해주도록 컨테이너에 bean으로 등록해준다는 것으로 이해해도 좋다.

Spring이 관리하는 객체를 bean이라고 한다. ★

※ 참고) 컨텍스트에 등록된 bean 정보(Role, 이름, 클래스 등) 조회하기

더보기

https://yjh5369.tistory.com/entry/spring-bean-%EB%93%B1%EB%A1%9D%EC%A0%95%EB%B3%B4-%EC%A1%B0%ED%9A%8C-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%81%B4%EB%9E%98%EC%8A%A4

* Bean의 role(역할)

1) ROLE_APPLICATION(=0) : 애플리케이션이 동작하는 중에 사용되는 bean이다. 개발자가 직접 작성하는 애플리케이션 로직 bean과, 스프링이나 외부 라이브러리에서 제공하는 클래스가 사용되는 애플리케이션 인프라 bean이 이에 속한다. 

2) ROLE_SUPPORT(=1) : 복합 구조의 bean을 정의할 때 보조적으로 사용되는 bean이다. (거의 사용 안함)

3) ROLE_INFRASTRUCTURE(=2) : 주로 전용 태그에 의해 등록되며, spring 컨테이너의 기능에 관여한다. 컨테이너가 bean을 생성할 때 프록시 생성 같은 특별한 작업을 하도록 지원한다.

 

IOC 컨테이너를 설정하는 방법에는 대표적으로 2가지가 있다.

  • xml
  • @(Annotation)

이 포스팅에서는 xml을 작성하는 방법을 설명하고, @(Annotation) 기법은 다음 포스팅에서 이어서 설명할 것이다.

 

xml 작성

먼저, Spring 에서는 컨테이너 설정을 위해 xml를 사용한다.

xml 기법의 장점은 무엇일까?

첫 번째로 유지보수 시 자바코드의 수정이 필요 없어지거나 대폭 줄일 수 있다는 것이다. xml 파일만 수정을 하면 된다.

두 번째로 객체의 생성과 설정을 외부에서 해오는 것이다보니 결합성을 떨어뜨릴 수 있다는 것이다.

특히 대형 프로젝트에서 효율이 좋아지게 되는 기법이다.

 

그렇다면 스프링이 관리하는 객체인 bean을 관리하는 예제를 살펴보자.

먼저 눈여겨봐야 할 파일 4가지가 있는데, 아래 사진을 참고하여 각 파일이 어디에 위치해 있는지 파악해두자.

  • DemoApplication.java : 메인 함수가 있는 파일
  • Calculator.java : 계산기 클래스
  • MyCalculator.java : 나만의 계산기 클래스
  • application.xml : Bean 설정 파일

 

 

<DemoApplication.java>

주석처리한 부분은 Spring을 적용하지 않은 단순 JAVA코드이고, 실제 실행되는 코드는 Bean 객체를 설정 파일로부터 가져와서 사용하는 소스 코드이다.

AbstactApplicationContext 클래스는 Context를 담는 컨테이너이며, 컨테이너가 구동되는 시점에 Bean 객체를 반환한다.

GenericXmlApplicationContext 클래스는 XML 설정 파일의 경로를 받아서 객체 생성과 초기화를 수행하여 이 객체에 접근할 수 있게 해주고, 인자를 2개 이상으로 하여 2개 이상의 XML 설정 파일의 경로를 받아서 같이 쓸 수도 있다.

getBean의 첫 번째 인자는 xml 설정 파일에서 지정한 bean의 id값이고 두 번째 인자는 반환 타입이다. 반환 타입이 유일하다면 첫 번째 인자는 생략해도 된다.

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		
		/*
		MyCalculator mCal = new MyCalculator();
		mCal.setCalculator(new Calculator());
		mCal.setA(7);
		mCal.setB(3);
		System.out.println(mCal.add());
		System.out.println(mCal.sub());
		*/
		
		String configLocation = "classpath:application.xml";
		AbstractApplicationContext ctx = new GenericXmlApplicationContext(configLocation);
		MyCalculator mCal = ctx.getBean("myCalculator", MyCalculator.class);
		System.out.println(mCal.add());
		System.out.println(mCal.sub());
		ctx.close();
	}

}

 

 

<Calculator.java>

덧셈/뺄셈 연산 메소드만 있는 클래스이다.

package com.example.demo;

public class Calculator {
	public int plus(int a,int b) {
		return a+b;
	}
	public int minus(int a,int b) {
		return a-b;
	}
}

 

 

<MyCalculator.java>

java bean에 해당하는 클래스이다. 앞으로 나올 bean 설정 파일(application.xml)에서 bean의 특정 변수값을 미리 지정할 수도 있는데, 이를 위해 해당 변수에 대한 setter 메소드가 반드시 존재해야 한다. setter 메소드는 이클립스 상단 메뉴의 Source에서 자동생성 해주는 기능을 찾을 수 있다.

package com.example.demo;

public class MyCalculator {
	private Calculator calculator;
	private int a;
	private int b;
	
	public Calculator getCalculator() {
		return calculator;
	}
	public void setCalculator(Calculator calculator) {
		this.calculator = calculator;
	}
	public int getA() {
		return a;
	}
	public void setA(int a) {
		this.a = a;
	}
	public int getB() {
		return b;
	}
	public void setB(int b) {
		this.b = b;
	}
	
	public int add() {
		return calculator.plus(a, b);
	}
	
	public int sub() {
		return calculator.minus(a, b);
	}
}

 

 

<application.xml>

bean 설정 파일이다. beans 태그에 있는 xmlns, xsi 값은 xml의 구조를 정의하는 스키마 파일이다.

특정 클래스에 대한 객체 id를 정하면, 객체를 받아오는 쪽은 아까 설명한 getBean 메소드의 첫 번째 인자에 이 id를 작성하면 된다.

이제 <property>를 통하여 bean의 수정자(setter)로 지정된 변수값들을 초기화할 수 있다. ref 속성은 참조할 bean의 id값을 가리킨다는 사실도 명심하자. 참고로, 클래스의 생성자를 이용하기 위해서는 <property> 태그가 아닌 <constructor-arg>를 이용하면 된다.

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="calculator" class="com.example.demo.Calculator"/>
    <bean id="myCalculator" class="com.example.demo.MyCalculator">
    	<property name="calculator">
    		<ref bean="calculator"/>
    	</property>
    	<property name="a" value="7"/>
    	<property name="b" value="3"/>
    </bean>
</beans>

※ <property>의 value 속성값에는 문자열, 정수, 실수, 클래스 등을 문자열로 작성할 수 있다. 스프링의 내장 변환기인 PropertyEditor가 문자열로 작성된 value 값을 선언 타입에 맞게 변환 해준다. Spring 3.0부터는 ConversionService를 사용할 수도 있다.

 

+추가) p 네임스페이스를 이용하는 방법도 있다.

 <?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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="calculator" class="com.example.demo.Calculator"/>
    <bean id="myCalculator" class="com.example.demo.MyCalculator" p:a="7" p:b="3">
    	<property name="calculator">
    		<ref bean="calculator"/>
    	</property>
    </bean>
</beans>

 

 

-------------------------------------------------------------------------------------------------------------------------

 

 

List에 대한 property 설정은 다음과 같이 <list> 태그를 이용하면 되고,

<property name="list_a">
    <list>
    	<value>1</value>
        <value>3</value>
        <value>5</value>
        <value>7</value>
    </list>
</property>
        

 

property방식 말고도 생성자를 이용하여 값을 설정하고 싶다면 <construct-arg> 태그를 이용하면 된다.

생성자 인자 순서대로 나열하면 되며, name 속성은 생략하면 된다.

<construct-arg value="7"/>
<construct-arg value="3"/>

 

+ 추가1) c 네임스페이스를 이용하여 생성자 변수의 값을 설정할 수도 있다.

<beans ...
	xmlns:c="http://www.springframework.org/schema/c"
    
    <bean id="id" class="package.class" c:a="7" c:b="3"/>
    ...
</beans>
     

 

 

@(Annotation) 기법은 다음 포스팅에서 다룰 것이다.

 

 

 

반응형

댓글