능글맞은 구렁이
Spring-의존성주입(인젝션) 본문
1. 의존성 관리
1. Dependency Lookup
컨테이너가 애플리케이션 운용에 필요한 객체를 생성하고 클라이언트는 컨테이너가 생성한 객체를
검색하여 사용하는 방식
※ 실제 애플리케이션 개발 과정에서는 사용하지 않는다.
2. Dependency Injection
객체 사이의 의존관계를 스프링 설정 파일에 등록된 정보를 바탕으로 컨테이너가 자동으로 처리해준다.
따라서 의존성 설정을 바꾸고싶을 때 프로그램 코드를 수정하지 않고 스프링 설정 파일 수정만으로 변경사항을
적용할 수 있어 유지보수가 향상된다.
*의존관계를 처리하는 메소드*
1) Setter Injection : setter 메소드 기반의 인젝션
2) Constructior Injection : 생성자 기반의 인젝션
※의존성이란? 객체와 객체의 결합 관계이다.
2. 생성자 인젝션 이용하기
1. 생성자 인젝션 이용하기
스프링 컨테이너는 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="polymorphism.SamsungTV">
<constructor-arg ref="sony"></constructor-arg>
</bean>
<bean id="sony" class="polymorphism.SonySpeaker"></bean>
</beans>
이처럼 <bean>객체가 두개라면 스프링 컨테이너는 등록된 순서대로 객체를 생성한다.
하지만 지금의 경우에는 id="tv"를 생성하기 위해서 생성자에게 id="sony"를 전달해 주어야 하기 때문에
(즉, 의존성 주입 때문에)id="sony"객체가 먼저 생성되고, id="tv"는 나중에 생성된다.
2. 다중 변수 매핑
생성자 인젝션에서 초기화해야 할 멤버변수가 여러 개이면, 여러 개의 값을 한꺼번에 전달해야 한다.
<?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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<bean id="tv" class="polymorphism.SamsungTV">
<constructor-arg index="0" ref="sony"></constructor-arg>
<constructor-arg index="1" value="2700000"></constructor-arg>
</bean>
<bean id="sony" class="polymorphism.SonySpeaker"></baen>
</beans>
<constructor-arg>엘리먼트에는 ref와 value 속성을 사용하여 생성자 매개변수로 전달값을 지정할 수 있다.
1) ref : 인자로 전달될 데이터가 <bean>으로 등록된 다른 객체일 때는 ref속성을
이용하여 해당 객체의 아이디나 이름을 참조
2) value : 고정된 문자열이나 정수 같은 기본형 데이터일 때는 value속성을 사용한다.
3) index : 생성자가 여러 개 오버로딩 되어있다면 어떤 생성자를 호출해야 할지 분명하지 않을 수 있는데 이때
index속성을 지원하며, index속성을 이용하면 어떤 값이 몇 번째 매개변수로 매핑되는지 지정할 수 있다.
3. 의존관계 변경
유지보수 과정에서 다른 클래스로 교체해야하는 상황이 발생하면 의존성 주입은 이런 상환을 매우
효과적으로 처리해준다. 아래와 같이 변경하려는 클래스를 <bean>으로 등록하고
sony부분을 apple로 변경해주면 된다.
<?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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<bean id="tv" class="polymorphism.SamsungTV">
<constructor-arg index="0" ref="apple"></constructor-arg>
<constructor-arg index="1" value="2700000"></constructor-arg>
</bean>
<bean id="sony" class="polymorphism.SonySpeaker"></baen>
<bean id="apple" class="polymorphism.AppleSpeaker"></baen>
</beans>
3. Setter 인젝션
1. Setter인젝션 기본
setter를 사용하려면 우선, 클래스 쪽의 변수들에 setter메소드를 추가해준다.
Setter 메소드는 스프링 컨테이너가 자동으로 호출하며, 호출하는 시점은 <bean>객체 생성 직후다.
따라서 Setter 인젝션이 동작하려면 클래스 쪽에 Setter메소드뿐만 아니라 기본 생성자도 반드시 필요하다.
이러한 Setter 인젝션을 이용하려면 스프링 설정 파일에 <property>엘리먼트를 사용해야 한다.
<?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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<bean id="tv" class="polymorphism.SamsungTV">
<property name="speaker" ref="apple"></property>
<property name="price" value="270000"></property>
</bean>
<bean id="sony" class="polymorphism.SonySpeaker"></baen>
<bean id="apple" class="polymorphism.AppleSpeaker"></baen>
</beans>
<property>의 name 속성값이 호출하고자 하는 메소드 이름이다. 즉 name속성값이 "speaker"라고 설정 되어 있으면 호출되는 메소드는 setSpeaker( )이다.
2. P 네임스페이스 사용하기
Setter인젝션을 설정할 때 '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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<bean id="tv" class="polymorphism.SamsungTV" p:speaker-ref="apple" p:price-value="270000">
</bean>
<bean id="sony" class="polymorphism.SonySpeaker"></baen>
<bean id="apple" class="polymorphism.AppleSpeaker"></baen>
</beans>
1) p:변수명-ref="참조할 객체의 이름이나 아이디" : 객체를 할당
2) p:변수명="설정할값" : 기본형이나 문자형 변수에 직접 값을 설정할 경우
4. 컬렉션 객체 설정
1. <list> : java.util.List, 배열
2. <set> : java.util.Set
3. <map> : java.util.Map
4. <props> : java.util.Properties
package polymorphism;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class CollectionBean {
/**List**/
private List<String> addressList;
public void setAddressList(List<String> addressList){
this.addressList= addressList;
}
public List<String> getAddressList(){
return addressList;
}
/**Set**/
private Set<String> addressList;
public void setAddressList(Set<String> addressList){
this.addressList= addressList;
}
public Set<String> getAddressList(){
return addressList;
}
/**Map**/
private Map<String, String> addressList;
public void setAddressList(Map<String, String> addressList){
this.addressList= addressList;
}
public Map<String, String> getAddressList(){
return addressList;
}
/**Propertis**/
private Properties addressList;
public void setAddressList(Properties addressList){
this.addressList=addressList;
}
public Properties getAddressList(){
return addressList;
}
}
public class CollectionBeanClient {
public static void main(String[] args) {
AbstractApplicationContext factory= new GenericXmlApplicationContext("applicationContext.xml");
CollectionBean bean = (CollectionBean)factory.getBean("collectionBean");
/**4. property**/
Properties addressList = bean.getAddressList();
Enumeration enu = addressList.propertyNames();
while(enu.hasMoreElements()) {
String ele = (String)enu.nextElement();
System.out.println(ele + " : " + addressList.getProperty(ele));
}
/**3. Map형식**/
Map<String, String> map=bean.getAddressList();
Set<String> s=map.keySet();
Iterator<String> itr=s.iterator();
while(itr.hasNext()){
String keyName=itr.next();
String value=map.get(keyName);
System.out.println(keyName + ":"+value);
}
/**2. set형식**/
Set<String> set=bean.getAddressList();
Iterator<String> keyInterator=set.iterator();
while(keyInterator.hasNext()){
System.out.println(keyInterator.next());
}
/**1. List형식
List<String> addressList=bean.getAddressList();
for(String address:addressList){
System.out.println(address.toString());
}
factory.close();
}
}
<?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">
<!-- list-->
<bean id="collectionBean" class="polymorphism.CollectionBean">
<property name="addressList">
<list>
<value>서울시 강남구 역삼동</value>
<value>인천시 서구 가좌동</value>
<value>경기도 고양시 일산</value>
</list>
</property>
</bean>
<!-- Collection : Set DI -->
<bean id="collectionBean" class="polymorphism.CollectionBean">
<property name="addressList">
<set>
<value>서울시 강남구 역삼동</value>
<value>인천시 서구 가좌동</value>
<value>경기도 고양시 일산</value>
</set>
</property>
</bean>
<!-- Collection :Map DI -->
<bean id="collectionBean" class="polymorphism.CollectionBean">
<property name="addressList">
<map>
<entry>
<key><value>고길동</value></key>
<value>서울시 강남구 역삼동</value>
</entry>
<entry>
<key><value>장보라</value></key>
<value>인천시 서구 가좌동</value>
</entry>
</map>
</property>
</bean>
<!-- Properties -->
<bean id="collectionBean" class="polymorphism.CollectionBean">
<property name="addressList">
<props>
<prop key="장보라">인천 서구 가좌동</prop>
<prop key="김두성">인천 연수구 동춘동</prop>
</props>
</property>
</bean>
</beans>
4. DI(의존성 주입) 정리!!
1. 생성자 의존성 주입
<beans~~~>
//하나의 객체만 전달받는 생성자의 경우
<bean~~~>
<constructor-arg ref="빈객체id"></constructor-arg>
</bean>
//객체와 값을 전달받는 생성자의 경우 ( 매개변수 선언 순서대로...)
<bean~~~>
<constructor-arg ref="빈객체id"></constructor-arg>
<constructor-arg value="값"></constructor-arg>
</bean>
//객체와 값(데이터타입지정)을 전달받는 생성자의 경우 ( 매개변수 선언 순서대로...)
<bean~~~>
<constructor-arg ref="빈객체id"></constructor-arg>
<constructor-arg>
<value type="데이터타입">값</value>
</constructor-arg>
</bean>
//매개 변수 선언 순서와 관계없이 값을 전달할 경우(index속성을 이용)
// 빈 클래스의 생성자 매개변수가 값, 객체의 순으로 정의 되어 있을 경우
<bean~~~>
<constructor-arg index="0" ref="빈객체id"></constructor-arg>
<constructor-arg index="1" value="값"></constructor-arg>
</bean>
</baens>
2. private 변수의 Setter를 이용한 의존성 주입
//기본형
<beans~~~>
<bean>
<property name="속성명(private변수명)" ref="빈객체id"></property>
<property name="속성명(private변수명)" ref="값"></property>
</bean>
</beans>
// p:Namespace를 이용
<beans~~~
xmlns:p="http://www.springframework.org/schema/p">
<bean ~~~ p:변수명-ref="빈객체id" p:변수명="값">
</bean>
</beans>
'Framework > Spring' 카테고리의 다른 글
Spring-DI/AOP정리! (0) | 2021.06.18 |
---|---|
Spring-Annotation(어노테이션) (0) | 2021.06.15 |
Spring-polymorphism(결합성테스트) (0) | 2021.06.15 |
Spring-사용방법, 프로젝트 생성시 주의 (0) | 2021.06.15 |
Spring-컨테이너종류, XML설정 (0) | 2021.06.14 |