능글맞은 구렁이

Spring-의존성주입(인젝션) 본문

Framework/Spring

Spring-의존성주입(인젝션)

보라색츄르 2021. 6. 15. 15:44

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>
Comments