객체를 미리 등록해 두고 뽑아다 쓰는 방식인 제어반전컨테이너(IOC)는 스프링프레임워크의 핵심기능 중 한 가지다.
◆ 제어 반전 컨테이너 ( IOC Container )
DI( Dependency Injection : 의존성 주입 )라는 개념을 사용해
Spring을 이용해 어플리케이션 제작을 하게 되면, 보통 객체를 직접적으로 생성하지 않고, 등록시켜 두고 뽑아다 쓰는 형태로 코드가 구현됨.
( 스프링의 객체 관리 기능 )
따라서 코드 자체를 수정하지 않고 등록시켜 둔 설정만 수정해 주면 되는 방식으로 돌아감.
IOC ( Inversion Of Controll / 제어 반전) Contaner
즉, 제어 반전 컨테이너는 등록 시킬 객체들을 저장 하고 있는 컨테이너개념
▶ IOC컨테이너 객체등록
1. spring bean Configuration File 생성
IOC컨테이너의 객체들은 spring bean Configuration File(xml파일)에서 등록시킨다.
JavaResource경로 아래 생성시킨다.
2. 설정파일에서 <bean>태그로 객체를 하나씩 등록
<bean> 태그는 객체를 IOC컨테이너에 등록시키는 태그이다.
- id : 객체를 불러올 때 쓰일 아이디
- class : 해당 객체의 클래스파일 경로
※ 인터페이스나 추상클래스는 등록이 불가하고, 기본적으로 등록되어있는 객체들도 있다.
▶ 객체 불러오기 ( 객체 주입 )
1. ApplicationContext객체 생성
코드에서 IOC컨테이너에 등록시킨 객체들을 불러오기 위해서 ApplicationContext객체를 이용하여 설정 파일의 경로를 잡고 이 객체를 이용하여 등록시킨 객체의 id또는 객체타입으로 객체를 불러올 수 있다.
-
- 선언
- ApplicationContext 변수명
-
- 생성
- new ClassPathXmlApplicationContext(“spring bean configuration File경로”);
2. ApplicationContext객체를 이용하여 객체 주입받기
등록된 객체는 ApplicationContext객체.getBean() 메서드를 이용하여 받아오고(주입), 인자에 따라 받아오는 방식이 달라진다.
※ id를 통해서 받기
등록한 객체의 아이디를 인자로 하게 되면 해당 아이디에 해당하는 객체를 뽑을 수 있다.
단, 아이디를 통해서 객체를 주입 받을 시 캐스팅이 필요하다.
※ type을 통해서 받기
인자로 객체타입.class를 하게 되면, 캐스팅 없이 해당 클래스 타입에 해당하는 객체를 바로 주입받을 수 있다.
해당 객체 또는 그 하위 객체가 등록되어있지 않거나, 해당 객체가 여러 개 또는 해당 객체 타입의 하위클래스가 여러 개 등록 돼있을 시 에러
=> 또한, IOC컨테이너 안에 기본적으로 포함되어 있는 객체들이 있기 때문에, Map.class등은 안될 수 있다.
※ 캐스팅 없이 id로 받기
첫 번째 인자로 아이디, 두 번째 인자로 해당 객체의 타입.class를 넘기게 되면 캐스팅을 하지 않고 바로 객체를 뽑을 수 있다.
▶ ApplicationContext객체의 그 외 메서드
-
- 등록된 객체의 개수 반환
- ctx.getBeanDefinitionCount();
-
- 등록된 객체의 id를 String배열로 반환
※ 위 메서드에서 반환하는 것은 자동적으로 등록되어있는 것을 제외한 설정 파일에서 등록된 객체의 수만 체크한다.
IOC컨테이너에 등록된 객체들은 기본적으로 컴파일 시 모두 자동적으로 생성자가 호출되면서 객체가 생성된다.
따라서 ApplicationContext객체로 주입 받은 객체들은 이미 생성된 객체들을 주입 받은 것이므로, 여러 개를 주입 받아와도 모두 같은 객체이다.
◆ 객체 생성자의 매개변수 설정
객체 등록 후 생성자의 매개변수를 설정하지 않을 경우 (인자가 없는)기본 생성자가 호출되면서 객체를 생성하기 때문에, 매개변수를 설정하지 않을 때 기본 생성자가 없을 경우 등록이 불가능하다.
▶ 기본형 타입의 인자가 있는 생성자를 가지고 있는 객체 등록
기본 생성자가 없고 인자가 있는 생성자만 있는 경우 생성자의 인자를 설정하지 않으면 등록이 불가능하다.
생성자의 매개변수는 <bean>태그 안에서 <constructor-arg> 태그를 이용하여 name과 value로 인자를 설정할 수 있다.
( 단, 인자로는 기본형데이터 + String 만 가능하다 )
-
name
: 생성자의 인자 name( 자동완성(ctrl+spacebar)으로 확인 가능 )
-
value
: 인자 값
( value값은 자동적으로 인자의 데이터 형에 맞게 변환되어 들어간다.)
▶ (기본형타입이 아닌)객체를 인자로 하는 생성자의 경우
기본형이나 String을 인자로 하지 않는 객체의 경우는 value옵션이 아닌 ref옵션으로 등록을 해야 한다.
또한 ref에는 매개변수로 할 객체의 id값이 들어가기 때문에 인자로 등록시킬 객체 또한 미리 등록을 시켜 둬야한다.
Ex) File객체를 인자로 하는 FileOutputStream일 경우
- File 객체 등록
- FileOutputStream객체 등록 및 생성자 인자설정
▶ value와 ref는 따로 설정할 수도 있다
※ value
※ ref
=> ref는 bean옵션을 이용하여 등록
-
태그를 설정할 때 같은 다른 타입의 같은 변수명을 사용하는 여러 개의 생성자가 있다면 type도 같이 설정해 줄 수도 있다. - 인자 값으로 null을 넣을 때 null값은 value가 아닌 <null/>태그를 이용하여 사용한다.
◆ 컬렉션을 인자로 사용할 때 설정
생성자의 인자로 기본형데이터나 String을 사용할 때는 value를 사용하고, 일반 객체를 사용할 때는 ref를 사용하지만, 컬렉션을 인자로 하는 경우 사용하는 방식이 다르다. 이는 생성자에만 적용되는 것은 아니다.
▶ List를 인자로 하는 생성자의 벨류값 설정
List는 <list>태그와 <value>태그를 사용하여 값을 넣는다.
( <list>태그의 디폴트는 ArrayList )
▶Set을 인자로하는 생성자의 벨류값 설정
Set은 <set>태그와 <value>태그를 이용하여 값을 넣는다.
( <set>태그의 디폴트는 LinkedHashSet )
( Set의 특성상 중복 값은 허용하지 않기 때문에 같은 값은 여러번 넣어도 효과가 없다. )
※ Set과 List는 같은 계열이기 때문에 set으로 만들어도 list로 받을 수 있고 반대의 경우도 가능하지만, Map으로는 캐스팅이 불가하다.
▶ Map을 인자로 하는 생성자의 벨류값 설정
Map은 <map>태그와 <entry>태그를 이용하여 값을 설정하고,키와 벨류 값들은
▶ Properties를 인자로 하는 생성자의 벨류값 설정
설정은 <props> 태그 안에 <prop key="키">벨류값</prop>으로 한다.
※ Properties ?
Properties는 <String,String>형태의 특수 맵이다.
이 객체를 쓰는 이유는 setProperty(String, String),getProperty(String, String)메서드를 사용하기 위해 쓰인다.
( getProperty(키,디폴트) : 키가 없을 경우 디폴트값이 출력되도록 하는 메서드 )
-
Property와 Map또한 같은 계열의 객체이기 때문에 캐스팅이 가능하다. 하지만, 이 역시 객체에 맞게 쓰는 것을 권장한다.
-
IOC컨테이너의 등록한 객체를 컬렉션 객체에 넣을 때는 value-ref옵션을 이용하여 등록한 객체의 아이디 값을 설정한다.
-
value-type으로 벨류 값의 타입을 지정할 수도 있다.