IoC(제어의 역행)
스프링 객체의 생성, 의존관계를 스프링에서 자동으로 관리
의존성(Dependency)는 객체와 객체와의 관계를 의미
Dependency Lookup : 컨테이너가 객체를 생성, 클라이언트는 생성한 객체를 검색해서 사용 (실 개발과정 미사용)
Denepdency Injection (Setter/Constructor Inection) : 컨테이너가 직접 객체들 사이에 의존관계를 처리
- Setter과 Constructor의 공통점 : 멤버변수를 원하는 값으로 설정하는것 목적
- 결과는 같으므로 어떤방법 쓰던지 상관없음
단, 코딩컨벤션 따라 한가지로 통일. 대부분은 Setter사용 / Setter메소드 제공되지 않는 클래스만 생성자인젝션
생성자 인젝션(Constructor Injection)
- xml에서 클래스 찾아서 객체생성시, 매개변수 없는 기본생성자를 호출
- 기본생성자 외에 매개변수를 가지는 다른 생성자 호출하도록 생성할 수 있음
- 생성자 인젝션을 사용해서, 생성자의 매개변수(예시:sony)로 의존관계에 있는 객체주소 정보 전달가능
- 예시 : <constructor-arg index="0" ref="apple"></constructor-arg> <constructor-arg index="1" value="2000000"></constructor-arg>
이클립스 자동 생성자 추가
생성하려는 클래스 열고 > alt + shift + s > Generate Constructor using Fields> 초기화할 멤버변수 선택후 OK
src/main/java/polymorphsim/SonySpeaker.java
package polymorphsim;
public class SonySpeaker {
public SonySpeaker() {
System.out.println("===> SonySpeaker 객체 생성");
}
public void volumeUp() {
System.out.println("SonySpeaker---소리 울린다.");
}
public void volumeDown() {
System.out.println("SonySpeaker---소리 내린다.");
}
}
src/main/java/polymorphsim/SamsungTV.java
package polymorphsim;
public class SamsungTV implements TV{
private SonySpeaker speaker;
private int price;
public SamsungTV() {
System.out.println("===> SamsungTV(1) 객체생성");
}
public SamsungTV(SonySpeaker speaker) {
System.out.println("===> SamsungTV(2) 객체생성");
this.speaker=speaker;
}
public SamsungTV(SonySpeaker speaker, int price) {
System.out.println("===> SamsungTV(3) 객체생성");
this.speaker = speaker;
this.price = price;
}
public void powerOn() {
System.out.println("SamsungTv --전원 켠다. (가격: "+price+")");
}
public void powerOff() {
System.out.println("SamsungTv --전원 끈다.");
}
public void volumeUp() {
speaker.volumeUp();
}
public void volumeDown() {
speaker.volumeDown();
}
}
src/main/resources/applicationContext.xml
<?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 ="tv" class="polymorphsim.SamsungTV">
<constructor-arg index="0" ref="sony"></constructor-arg>
<constructor-arg index="1" value="2000000"></constructor-arg>
</bean>
<bean id = "sony" class="polymorphsim.SonySpeaker"></bean>
</beans>
실행결과
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [applicationContext.xml]
INFO : org.springframework.context.support.GenericXmlApplicationContext - Refreshing org.springframework.context.support.GenericXmlApplicationContext@290dbf45: startup date [Tue Jan 04 00:06:47 KST 2022]; root of context hierarchy
===> SonySpeaker 객체 생성
===> SamsungTV(3) 객체생성
SamsungTv --전원 켠다. (가격: 2000000)
SonySpeaker---소리 울린다.
SonySpeaker---소리 내린다.
SamsungTv --전원 끈다.
INFO : org.springframework.context.support.GenericXmlApplicationContext - Closing org.springframework.context.support.GenericXmlApplicationContext@290dbf45: startup date [Tue Jan 04 00:06:47 KST 2022]; root of context hierarchy
- 객체 생성할때, 기본생성자가 아닌, 세번째 SaumsungTV(Speaker speakr, int price) 생성자가 사용됨.
- bean등록 순서대로 객체를 처리하는데, 생성자 인젝션으로 의존성 주입될 SonySpeaker가 먼저 객체생성SonySpeaker 객체를 매개변수로 받아들이는 생성자를 호출하여 객체 생성
- <constructor-arg>엘리먼트의 인자로 전달될 데이터가 <bean>인 다른 객체인경우 ref속성, 고정 문자열/정수인경우는 value
- 생성자 여러개 오버로딩 된 경우, index속성 통해 어떤값이 몇번째 매개변수로 매핑되는지 지정가능. 0부터시작
이클립스 자동 인터페이스 생성
생성할 인터페이스의 자식 열고 > alt + shift + T > Extract Interface> 생성할 인터페이스 이름/메소드 선택후 OK
* 체크박스 전체해제
src/main/resources/applicationContext.xml
<?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 ="tv" class="polymorphsim.SamsungTV">
<constructor-arg index="0" ref="apple"></constructor-arg>
<constructor-arg index="1" value="2000000"></constructor-arg>
</bean>
<bean id = "sony" class="polymorphsim.SonySpeaker"></bean>
<bean id = "apple" class="polymorphsim.AppleSpeaker"></bean>
</beans>
자바코드 수정없이, <constructor-arg 의 ref를 "sony"대신 "apple"로 변경하여 AppleSpeaker호출가능
<추가 생성/수정한 파일>
(interface) Speaker.java
(class) SonySpeaker.java
(class) AppleSpeaker.java
(class) SamsungTV.java >> 매개변수/멤버변수를 SonySpeaker대신, Speaker로 변경
Setter Injection
- Setter메소드 호출해서 의존성 주입을 처리
- 대부분 생성자 주입 보다 setter 주입 사용
- Setter메소드는 스프링 컨테이너가 자동으로 호출, 호출시점은 <bean> 객체 생성 직후
Setter인젝션 동작하려면, Setter메소드 뿐만 아니라, 기본 생성자도 반드시 필요
- 예시 : <constructor-arg index="0" ref="apple"></constructor-arg> <constructor-arg index="1" value="2000000"></constructor-arg>
이클립스 자동 생성자 추가
생성하려는 클래스 열고 > alt + shift + s > Generate Getter and Setters > 초기화할 멤버변수 선택후 OK
src/main/resources/applicationContext.xml
<?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 ="tv" class="polymorphsim.SamsungTV">
<!-- Setter 주입 -->
<property name="speaker" ref="apple"></property>
<property name="price" value="2000000"></property>
</bean>
<bean id = "sony" class="polymorphsim.SonySpeaker"></bean>
<bean id = "apple" class="polymorphsim.AppleSpeaker"></bean>
</beans>
- <property> 엘리먼트사용 필요, name속성값이 호출하려는 메소드이름
- Setter 메소드 이름 : setSpeaker()
- name 속성값 : name ="speaker" (첫문자 대문자로 바꾸고 set붙인 차이..) - 생성자주입처럼, Setter 메소드 호출하면서 다른 <bean>객체를 인자로 넘기려면 ref속성, 기본형데이터는 value속성
실행결과
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [applicationContext.xml]
INFO : org.springframework.context.support.GenericXmlApplicationContext - Refreshing org.springframework.context.support.GenericXmlApplicationContext@69a10787: startup date [Tue Jan 04 00:37:45 KST 2022]; root of context hierarchy
===> SamsungTV(1) 객체생성
===> AppleSpeaker 객체 생성
===> setSpeaker() 호출
===> setPrice() 호출
===> SonySpeaker 객체 생성
SamsungTv --전원 켠다. (가격: 2000000)
AppleSpeaker-- 소리 올린다.
AppleSpeaker-- 소리 내린다.
SamsungTv --전원 끈다.
INFO : org.springframework.context.support.GenericXmlApplicationContext - Closing org.springframework.context.support.GenericXmlApplicationContext@69a10787: startup date [Tue Jan 04 00:37:45 KST 2022]; root of context hierarchy
p 네임스페이스 사용
applicationContext.xml에 추가
xmlns:p="http://www.springframework.org/schema/p"
구분 | 규칙 |
참조형 변수에 객체 할당 | p:변수명-ref = "참조할 객체의 이름이나 아이디" p:speaker-ref="sony" |
기본형이나 문자형에 직접 값 설정 | p:변수명="설정할 값" p:price='2000000" |
(p네임스페이스 적용전)
<bean id ="tv" class="polymorphsim.SamsungTV" >
<property name="speaker" ref="apple"></property>
<property name="price" value="2000000"></property>
</bean>
(p 네임스페이스 적용후)
</bean id="tv" class="polymorphsim.samsungtv" p:speaker-ref="sony" p:price="2000000">
sts기능으로 p네임스페이스 추가방법
컬렉션 객체 설정
스프링에서 컬렉션 매핑과 관련된 엘리먼트들을 지원.
컬렉션 유형 | 엘리먼트 | 비고 |
java.util.List, 배열 | <list> | 리스트 |
java.util.Set | <set> | 중복미허용 |
java.util.Map | <map> | key,value |
java.util.Properties | <props> | key=value |
List
src/main/java/com/springbook/ioc/injection/CollectionBean.java
package com.springbook.ioc.injection;
import java.util.List;
import java.util.Set;
public class CollectionBean {
private List<String> addressList;
public void setAddressList(List<String> addressList) {
this.addressList = addressList;
}
}
src/main/resources/applicationContext.xml
<bean id ="collectionBean" class="com.springbook.ioc.injection.CollectionBean">
<property name="addressList">
<list>
<value>경기도</value>
<value>서울</value>
</list>
</property>
</bean>
--> applicationContext에도 <list>엘리먼트 사용
Set (중복미허용)
src/main/java/com/springbook/ioc/injection/CollectionBean.java
package com.springbook.ioc.injection;
import java.util.List;
import java.util.Set;
public class CollectionBean {
private Set<String> addressList;
public void setAddressList(Set<String> addressList) {
this.addressList = addressList;
}
}
src/main/resources/applicationContext.xml
<bean id ="collectionBean" class="com.springbook.ioc.injection.CollectionBean">
<property name="addressList">
<set value-type="java.lang.String">
<value>서울시 강남구</value>
<value>서울시 강서구</value>
<value>서울시 강서구</value>
</set>
</property>
</bean>
--> applicationContext에도 <set value-type="java.lang.String" > 엘리먼트 사용
set이 중복 제거해주므로, 출력결과는 서울시 강남구, 서울시 강서구 2건만 나옴
main
package com.springbook.ioc.injection;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.Properties;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import com.springbook.ioc.injection.CollectionBean;
public class CollectionBeanClient {
public static void main(String[] args) {
AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");
CollectionBean bean = (CollectionBean) factory.getBean("collectionBean");
// List, Set, Map, Properties에 맞게 변경
Set<String> addressList = bean.getAddressList();
for(String address : addressList) {
System.out.println(address.toString());
}
factory.close();
}
}
'IT > SPRING' 카테고리의 다른 글
[Spring] Interceptor (0) | 2023.06.02 |
---|---|
[SPRING] 어노테이션 설정 (0) | 2022.01.05 |
[SPRING] 스프링 컨테이너, applicationContext 설정파일 (0) | 2022.01.03 |
[SPRING] 프레임워크 개요 (0) | 2022.01.02 |
[환경셋팅] 스프링 개발 환경 셋팅 (0) | 2021.12.28 |