스프링 DI - [Dependency Injection]

728x90

[의존성 주입] : DI (Dependency Injection)

-Bean 객체 생성 시, 해당 Bean 객체가 관리할 값이나 객체를 주입해주는 것 의미

-Bean 객체 생성 후, Bean 객체가 가질 기본 값을 xml코드에서 주입해주는 개념

-
객체 간의 의존을 주입한다는 것
.

11강. [생성자를 통한 주입]

[생성자를 통한 주입]

-Bean 정의할 때,  <contructor-arg> 태그 이용해서 값을 주입

value      : 기본 자료형 값과 문자열 값 설정
ref          : 객체를 설정
type        : 저장할 값의 타입 설정
index       : 지정된 값을 주입할 생성자의 매개변수 인덱스 번호

[객체 주입]

    1) 직접 객체 생성하여 객체 주입하기

    2) 이미 존재하는 객체를 ref 속성으로 지정하여 주입하기

kr.co.softcampus.config.[beans.xml] 빈 등록

	<!-- Bean 등록 -->
	<bean id='obj1' class='kr.co.softcampus.beans.TestBean1' lazy-init='true' />
	<bean id='obj2' class='kr.co.softcampus.beans.TestBean1' lazy-init='true'>
		<constructor-arg value='100' type='int' /> //주입 값 
	</bean>
  //기본적으로 스프링은 String > double > int 순으로 우선 처리함 
	<bean id='obj3' class='kr.co.softcampus.beans.TestBean1' lazy-init='true'>
		<constructor-arg value='11.11' type='double' />
	</bean>
	<bean id='obj4' class='kr.co.softcampus.beans.TestBean1' lazy-init='true'>
         <constructor-arg value='문자열' />
	</bean>
          
  //기본적으로 스프링은 생성자 여러 개일 때 값을 순서대로 줘야 함 
	<bean id='obj5' class='kr.co.softcampus.beans.TestBean1' lazy-init='true'>
		<constructor-arg value='200' type='int' />
		<constructor-arg value='22.22' type='double' />
		<constructor-arg value='안녕하세요' type='java.lang.String' />
	</bean>
  //단, index 속성으로 순서 지정해줄 수도 있음 
	<bean id='obj7' class='kr.co.softcampus.beans.TestBean1' lazy-init='true'>
		<constructor-arg value='33.33' type='double' index='1' />
		<constructor-arg value='33' type='int' index='2' />
		<constructor-arg value='안녕하세요' type='java.lang.String' index='3' />
	</bean>

  //생성자에 객체 의존 주입할 때, 빈 등록 시 의존 주입 대상 객체도 한 번 생성 해준 뒤, 값 줌 
	<bean id='obj8' class='kr.co.softcampus.beans.TestBean2' lazy-init='true'>
		<constructor-arg> //여기서 값을 줄 때, 의존 주입 대상 객체 생성하여 값을 줌 
			<bean class='kr.co.softcampus.beans.DataBean' />
		</constructor-arg>
		<constructor-arg>
			<bean class='kr.co.softcampus.beans.DataBean' />
		</constructor-arg>
	</bean>

   //의존 주입 대상 객체가 이미 존재하는 개체인 경우, ref 속성으로 주입 객제 직접 지정 
	<bean id='data_bean' class='kr.co.softcampus.beans.TestBean2' lazy-init='true'>
		<constructor-arg ref='data_bean' />
		<constructor-arg ref='data_bean' />
	</bean>

</beans>
 

12강. [Setter 메소드를 통한 주입]

[Setter 메소드 통한 주입]

 -Bean 객체가 가질 기본 값을 Setter() 메소드 통해 주입 가능                                                                         

 -Bean 정의할 때, <property> 태그 사용하여 의존 주입 값 넣음 

name : 데이터를 주입할 프로퍼티 이름
value : 기본 자료형 및 문자열 주입할 때 사용하는 속성
ref : 객체 주소값 주입할 때 사용하는 속성

[객체 주입]

      1) 직접 객체 생성하여 주입하기

<bean id = 't1' class = 'kr.co.softcampus.beans.TestBean'>
	<property name = "data5"> //내부에 주입 대상 객체 정의하고 주입 
		<bean class='kr.co.softcampus.beans.DataBean' />
	</property>
</bean>

      2) 이미 정의되어 있는 객체를 ref 속성으로 지정하여 주입하기

<bean id = 't1' class = 'kr.co.softcampus.beans.TestBean'>
          //이미 정의되어 있는 객체를 ref속성으로 지정하여 주입 
	<property name = "data6" ref = "data_bean" />
</bean> 
<bean id = 'data_bean' class='kr.co.softcampus.beans.DataBean'/> //이미 정의된 객체

13강. [컬렉션 주입]

[컬렉션 주입]

-Bean에 주입하는 멤버가 컬렉션인 경우, 컬렉션이 관리할 객체를 초기에 설정할 수 있다.

           ex. List/ Map/ Set/ Property

-Bean에 주입할 멤버 타입이 컬렉션인 경우, 다시 컬렉션이 관리할 객체를 초기에 설정할 수 있다.

[List]

1) 객체 단위 리스트에 객체 주입 시, 직접 생성 후 주입 가능

2) 객체 단위 리스트에 객체 주입 시, 이미 정의된 빈을 ref 속성으로 지정하여 주입 가능

[Set]

-중복된 값은 담지 못함(정수값, 실수값 동일값인 경우 또 못 담음)

-중복된 객체는 담지 못함(동일한 종류, 즉 주소값 같은 객체는 다시 못담음)


kr.co.softcampus.beans.[TestBean.java]   //빈 등록될 객체

public class TestBean {
	//필드
	// 컬렉션 : <List>
	private List<String> list1; //컬렉션 리스트 
	private List<Integer> list2;
	private List<DataBean> list3; //객체 담는 리스트
	// 컬렉션 : <Set>
	private Set<String> set1;
	private Set<Integer> set2;
	private Set<DataBean> set3;
	// 컬렉션 : <Map>
	private Map<String, Object> map1;
	// 컬렉션 : <Properties>
	private Properties prop1;

          ...get/set() 메소드 

}

kr.co.softcampus.config.[beans.xml]  //xml파일에 빈 등록

	<!-- Bean 등록 -->
	<bean id='t1' class='kr.co.softcampus.beans.TestBean'>
		<!--제네릭이 String인 List -->
		<property name="list1">
			<list>
				<value>문자열1</value>
				<value>문자열2</value>
				<value>문자열3</value>
			</list>
		</property>
		<!-- 제네릭이 Integer인 List -->
		<property name="list2">
			<list>
				<value type='int'>100</value>
				<value type='int'>200</value>
				<value type='int'>300</value>
			</list>
		</property>
		<!-- 제네릭이 DataBean인 list -->
		<property name="list3">
			<list>
				<bean class='kr.co.softcampus.beans.DataBean'/>
				<bean class='kr.co.softcampus.beans.DataBean'/>
				<ref bean = 'data_bean'/>
				<ref bean = 'data_bean'/>
			</list>
		</property>
		
		<!-- 제네릭이 String인 Set -->
		<property name = "set1">
			<set>
				<value>문자열1</value>
				<value>문자열2</value>
				<value>문자열3</value>
			</set>
		</property>
		<!--제네릭이 Integer인 Set -->
		<property name = "set2">
			<set>
				<value type = 'int'>100</value>
				<value type = 'int'>200</value>
				<value type = 'int'>300</value>
			</set>
		</property>
		<!-- 제네릭이 DataBean인 Set -->
		<property name = "set3">
			<set>
				<bean class='kr.co.softcampus.beans.DataBean'/>
				<bean class='kr.co.softcampus.beans.DataBean'/>
				<ref bean='data_bean'/>
				<ref bean='data_bean'/>
			</set>
		</property>
		<!-- 제네릭이 String, Object인 Map -->
		<property name='map1'>
			<map>
				<entry key='a1' value='문자열'/>
				<entry key='a2' value='100' value-type='int'/>
				<entry key = 'a3'>
					<bean class='kr.co.softcampus.beans.DataBean'/>
				</entry>
				<entry key='a4' value-ref='data_bean'/>
				<entry key='a5'>
					<list>
						<value>문자열1</value>
						<value>문자열2</value>
						<value>문자열3</value>
					</list>
				</entry>
			</map>
		</property>
		<property name='prop1'>
		 	<props>
		 		<prop key='p1'>문자열1</prop>
		 		<prop key='p2'>문자열2</prop>
		 		<prop key='p3'>문자열3</prop>
		 	</props>
		</property>
		
	</bean>

<bean id = 'data_bean' class='kr.co.softcampus.beans.DataBean' scope = 'prototype'/>
</beans>

kr.co.softcampus.main.[MainClass.java]

public class MainClass {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("kr/co/softcampus/config/beans.xml");

		TestBean t1 = ctx.getBean("t1", TestBean.class);
		List<String> list1 = t1.getList1();
		for(String str: list1) {
			System.out.printf("list1 : %s\n", str);
		}
		List<Integer>list2 = t1.getList2();
		for(int value : list2) {
			System.out.printf("list2 : %d\n", value);
		}
		List<DataBean>list3 = t1.getList3();
		for(DataBean obj : list3) {
			System.out.printf("list3 : %s\n", obj);
		}
		System.out.println("----------------");
		
		//Set의 경우 중복된 값을 주입할 경우 하나만 인식하고 더 이상 담지 X
		Set<String> set1 = t1.getSet1();
		Set<Integer> set2 = t1.getSet2();
		Set<DataBean> set3 = t1.getSet3();
		
		for(String str: set1) {
			System.out.printf("set1: %s\n", str);
		}
		for(int value: set2) {
			System.out.printf("Set2: %s\n", value);
		}
		for(DataBean obj : set3) {
			System.out.printf("Set3:%s\n", obj);
		}
		System.out.println("----------------");
	
		Map<String, Object> map1 = t1.getMap1();
		
		String a1 = (String)map1.get("a2");
		int a2 = (Integer)map1.get("a3");
		DataBean a3 = (DataBean)map1.get("a4");
		DataBean a4 = (DataBean)map1.get("a5");
		List<String> a5 = (List<String>)map1.get("a5");
		
		System.out.printf("a1:%s\n", a1);	
		System.out.printf("a2:%d\n", a2);	
		System.out.printf("a3:%s\n", a3);	
		System.out.printf("a4:%s\n", a4);	

		for(String str: a5) {
			System.out.printf("a5", str);
		}
		System.out.println("----------------");	
		//프로퍼티 타입 = 문자열 값만 사용
		Properties prop1 = t1.getProp1();
		String p1 = prop1.getProperty("p1");
		String p2 = prop1.getProperty("p2");
		String p3 = prop1.getProperty("p3");
		
		System.out.printf("p1 : %s\n", p1	);
		System.out.printf("p2 : %s\n", p2	);
		System.out.printf("p3 : %s\n", p3	);
		
				
		ctx.close();
		
	}

실행 결과 화면&amp;amp;amp;nbsp;


14강. [자동 주입]

[자동 주입]

-Bean 정의 시, 객체 직접 주입은 기본적으로 생성자/setter()를 통해 했다.
-그런데, Spring은 객체 자동 주입 기능을 제공한다.
-자동 주입은 이름/타입/생성자를 통해 가능하며 <auto wire> 로 적용된다.
             * 자동 주입 대상은 오직 객체만 가능. String or int 타입은 직접 주입함

[이름을 통한 주입]

-byName : 빈 객체의 프로퍼티 이름과 정의된 빈 이름이 같은 것을 찾아서 자동으로 주입됨

<bean id='obj2' class='kr.co.softcampus.beans.TestBean1' autowire='byName'/>


<bean id='data1' class='kr.co.softcampus.beans.DataBean1'/>
<bean id='data2' class='kr.co.softcampus.beans.DataBean1'/>

- 빈으로 등록한 TestBean1 의 경우, 내부에 data1/data2 로 이름지어진 DataBean1 타입의 객체 필드를 가지고 있다. 빈 등록 시, autowire 속성 값에 ‘byName’을 주었으므로 이 빈은 내부의 객체 주입 시, 이름을 우선하여 자동 주입을 할 것이다.

[타입을 통한 주입]

-byType : 빈 객체의 프로퍼티 타입과 정의된 빈의 타입이 일치할 경우 자동 주입된다.

-이 때, 동일 타입 빈이 2개 이상 정의되어 있을 경우 오류 발생함

<bean id='obj3' class='kr.co.softcampus.beans.TestBean2' autowire='byType'/>


<bean id ='data_bean2' class='kr.co.softcampus.beans.DataBean2'/>

- 빈으로 등록한 TestBean2 의 경우, 내부에 DataBean2 타입의 객체 필드를 가지고 있다.

빈 등록 시, autowire 속성 값에 ‘byTytpe’을 주었으므로 이 빈은 내부의 객체 주입 시, 타입을 우선하여 자동 주입을 할 것이다.

[생성자를 통한 주입]

-constructor : 생성자의 매개변수 타입과 정의된 빈의 타입이 일치할 경우 자동 주입된다.

-이 때, 동일 타입 빈이 2개 이상 정의되어 있을 경우 오류 발생함

<bean id='obj7' class='kr.co.softcampus.beans.TestBean3' autowire='constructor'>
        <constructor-arg value='200' index='0' type = 'int'/>
        <constructor-arg value='문자열2' index='1' />
</bean>

- 빈으로 등록한 TestBean3 의 경우, 내부에 DataBean2 타입 객체를 매개변수로 갖는 생성자를 가지고 있다. 빈 등록 시, autowire 속성 값에 ‘constructor’ 값을 주었으므로 이 빈은 내부의 객체 주입 시 생성자의 매개변수 타입과 일치하는 타입의 빈을 우선하여 자동 주입할 것이다.

[따로 자동 주입 설정하지 않을 경우, 기본 자동 주입에 대한 설정도 가능]

default-autowire ='byName’

 

[참고] - SpringFramework 개발자를 위한 실습을 통한 입문 과정

728x90