[Spring] DI(의존성주입)2

김장환·2022년 8월 19일

Spring

목록 보기
4/17

DI(의존성주입)

저번에 정리한 DI에 이어 이번에도 DI이에 대해 정리하여한다.
여러가지 예시를 통해 정리 및 설명을 하려한다.

src/main/resource에 xml 생성

  • 이전에는 각 패키지마다 xml을 하나씩 따로따로 설정했지만 src/main/resource에 xml을 생성하면 전역으로 사용할수 있다.
  • 따라서 생성한 xml파일 하나로 여러 패키지의 프로젝트에 다 적용할 수 있다.
  • 이렇게 안하면 프로젝트마다 xml을 하나씩 다만들어야되서 불편하다.

여기서는 xml파일명을 applicationContext.xml 로 생성했으며 쭉 이 파일을 이용할것이다.


p 네임스페이스

우선 파일을 순서대로 만들면서 정리하고 마지막에 p네임스페이스를 적용하고자 한다.

1. SmsSender.java를 생성한다.
두 클래스를 연결하기 위한 has a 관계로 사용된다

package spring3;

//문자전송 시스템
public class SmsSender {
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "SmsSender call";
	}
}

2. SystemMoniter.java를 생성한다.

  • has a관계 두 클래스가 연결
  • 메개변수를 설정하는데 그중 하나는 위의 SmsSender을 has a관계를 통해 사용
package spring3;

//문자를 전송=>기간을 정하기
public class SystemMoniter {

	private long periodTime;//기간
	//has a 관계 =>두 클래스가 연결
	private SmsSender sender;
	//Setter Method
	public void setPeriodTime(long periodTime) {
		this.periodTime = periodTime;
		System.out.println("setPeriodTime() call");
	}
	public void setSender(SmsSender sender) {
		this.sender = sender;
		System.out.println("setSender() call=>"+sender);
	}
	
	@Override
	public String toString() {// Setter메서드로 잘 설정됐는지 확인할수있음
		// TODO Auto-generated method stub
		return "SystemMoniter[periodTime="+periodTime+",sender="+sender+"]";
	}
}

3. applicationContext.xml에 내용 추가

  • bean을 생성하고 id를 moniter로 하고자 한다.
  • Setter Method로 인해 Property를 사용한다.
  • 변수 2개를 설정하되 sender는 연결을 위한 매개변수(has a관계) 이기에 ref를 사용한다.

<bean id="moniter" class="spring3.SystemMoniter">
<property name="periodTime">
		<value>10</value>
	</property>
	<property name="sender">
		<ref bean="smsSender" />
	</property> 
</bean>

4. Main.java를 생성한다.

  • 이전에 만든 Main을 가져오되 경로대신 배열, 빈팩토리 대신 context을 작성하고 자동종료,객체 가져와서 처리, 종료를 하게 만든다.
package spring3;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	public static void main(String[] args) {
	// TODO Auto-generated method stub
	//1.메모리관리->xml파일이 여러개->배열로 관리->파일명부여  // xml이 여러개면 ,로 쭉쭉 나열 가능
		String [] configLocation=new String[] {"applicationContext.xml"};	
	//2.xml파일을 메모리에 올려줄 수 있는 클래스를 통해서 객체를 생성
		AbstractApplicationContext context=
			new ClassPathXmlApplicationContext(configLocation);
	//3.자바프로그램이 종료->자동적으로 context객체도 같이 종료 설정	
		context.registerShutdownHook();
	//4.xml에서 만들어진 객체를 가져와서 처리	
		SystemMoniter moniter=(SystemMoniter)context.getBean("moniter");
		System.out.println("moniter=>"+moniter);//moniter객체를 형변환해서 얻어오면 SmsSender도 얻어올수있다
	//5.context도 종료
		context.close();//메모리에 올려놓은 모든 빈즈객체->메모리해제
    }

}

5. xml에 작성한 내용 p 네임스페이스로 변환

  • Setter method일때 property태그를 사용하고 그안에 값을 넣어준다.
    하지만 p네임스페이스로 변환하면 보다 간단하게 작성할수있다.

  • 형식) p:멤버변수명="값" p:멤버변수명-ref="상대방 빈즈의 id값"

빈즈에 id, class를 부여하고 이어서 p:멤버변수명="값" 이런식으로 입력하면 property와 value를 사용하지 않고 간단히 작성할 수 있다.

p네임스페이스에서 객체가있으면 ref 없으면 ref안쓰고 사용한다.

아까 작성한 xml파일인
<bean id="moniter" class="spring3.SystemMoniter">
<property name="periodTime">
		<value>10</value>
	</property>
	<property name="sender">
		<ref bean="smsSender" />
	</property> 
</bean>
을 p네임스페이스를 사용하면 
<bean id="moniter" class="spring3.SystemMoniter" p:periodTime="20" p:sender-ref="smsSender">
이렇게 한줄로 가능


e 네임스페이스

이것도 마찬가지로 우선 파일을 순서대로 만들면서 정리하고 마지막에 e네임스페이스를 적용하고자 한다.

1. SmsSender을 생성한다.

  • 위의 예시와 변함이 없기에 그대로 가져온다.
package spring3;

//문자전송 시스템
public class SmsSender {
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "SmsSender call";
	}
}

2. SystemMoniter.java를 생성한다.

  • 이전의 예시와 다르게 Setter Method 대신 생성자를 사용한다.

package spring4;

//문자를 전송=>기간을 정하기
public class SystemMoniter {

	private long periodTime;//기간
	//has a 관계 =>두 클래스가 연결
	private SmsSender sender;
	
	//생성자를 이용->c네임스페이스를 이용해서 설정이 가능
	public SystemMoniter(long periodTime, SmsSender sender) {
		this.periodTime = periodTime;
		this.sender = sender;
		System.out.println("SystemMoniter() Constructor call");
	}
	//----------------------------------------
	@Override
	public String toString() {// Setter메서드로 잘 설정됐는지 확인할수있음
		// TODO Auto-generated method stub
		return "SystemMoniter[periodTime="+periodTime+",sender="+sender+"]";
	}
}

3. applicationContext.xml에 내용 추가

  • 생성자이기에 constructor-arg를 사용한다.
<bean id="moniter2" class="spring4.SystemMoniter">
 	<constructor-arg value="10" />
	<constructor-arg ref="smsSender2" /> 
</bean>  

4. Main.java를 생성한다.

  • 이전꺼에서 id값인 moniter를 moniter2로만 수정한다.
package spring4;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//1.메모리관리->xml파일이 여러개->배열로 관리->파일명부여  // xml이 여러개면 ,로 쭉쭉 나열 가능
			String [] configLocation=new String[] {"applicationContext.xml"};	
		//2.xml파일을 메모리에 올려줄 수 있는 클래스를 통해서 객체를 생성
			AbstractApplicationContext context=
					new ClassPathXmlApplicationContext(configLocation);
		//3.자바프로그램이 종료->자동적으로 context객체도 같이 종료 설정	
			context.registerShutdownHook();
		//4.xml에서 만들어진 객체를 가져와서 처리	
			SystemMoniter moniter=(SystemMoniter)context.getBean("moniter2");
			System.out.println("moniter2=>"+moniter);//moniter객체를 형변환해서 얻어오면 SmsSender도 얻어올수있다
		//5.context도 종료
			context.close();//메모리에 올려놓은 모든 빈즈객체->메모리해제
	}

}

5. xml에 작성한 내용 e네임스페이스로 변환

  • 생성자일때 constructor-arg태그를 사용하고 그안에 값을 넣어준다.
    하지만 e네임스페이스로 변환하면 보다 간단하게 작성할수있다.

  • 형식) e:멤버변수명="값" e:멤버변수명-ref="상대방 빈즈의 id값"

빈즈에 id, class를 부여하고 이어서 e:멤버변수명="값" 이런식으로 입력하면 constructor-arg 와 value를 사용하지 않고 간단히 작성할 수 있다.

e네임스페이스에서 객체가있으면 ref 없으면 ref안쓰고 사용한다.


아까 작성한 xml파일인
<bean id="moniter2" class="spring4.SystemMoniter">
 	<constructor-arg value="10" />
	<constructor-arg ref="smsSender2" /> 
</bean>  
을 e네임스페이스를 사용하면 
<bean id="moniter" class="spring3.SystemMoniter" <bean id="moniter2" class="spring4.SystemMoniter" c:periodTime="30" c:sender-ref="smsSender2">
이렇게 한줄로 가능

익명의 빈즈객체를 전달, 네임스페이스 혼용사용

익명의 빈즈객체를 전달받는방법과 네임스페이스를 혼용사용이 가능한걸 정리하고자 한다.

이것도 마찬가지로 우선 파일을 순서대로 만들면서 정리하고자 한다.

1. SmsSender 생성

  • 이전과 다르게 생성자를 만들어준다.

package spring5;

//문자전송 시스템
public class SmsSender {
	boolean flag;//문자가 제대로 전달됐는지 체크
	
	//constructor-arg
	public SmsSender(boolean flag) {
		this.flag=flag;
	}
	//-------------------------------------
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "SmsSender call";
	}
}

2. SystemMoniter.java를 생성한다.

  • 이전 예제와 변항이 없기에 그대로 가져온다.

package spring5;

//문자를 전송=>기간을 정하기
public class SystemMoniter {

	private long periodTime;//기간
	//has a 관계 =>두 클래스가 연결
	private SmsSender sender;
	
	//Setter Method
		public void setPeriodTime(long periodTime) {
			this.periodTime = periodTime;
			System.out.println("setPeriodTime() call");
		}
		public void setSender(SmsSender sender) {
			this.sender = sender;
			System.out.println("setSender() call=>"+sender);
		}
	//----------------------------------------
	@Override
	public String toString() {// Setter메서드로 잘 설정됐는지 확인할수있음
		// TODO Auto-generated method stub
		return "SystemMoniter[periodTime="+periodTime+",sender="+sender+"]";
	}
}

3. applicationContext.xml에 내용 추가

  • 반은 네임스페이스 반은 기존방식으로 사용가능하다.
  • bean은 2개를 생성하는데 하나는 SystemMoniter의 객체들이고 또다른 하나는 SmsSender의 객체다

<bean id="moniter3" class="spring5.SystemMoniter" p:periodTime="50">
  <property name="sender">
  	 <ref bean="smsSender3" />
  </property>
</bean>    이런식으로 반은 네임스패이스 반은 기존방식으로도 사용가능하다.
    
<bean id="smsSender3" class="spring5.SmsSender">
	<constructor-arg value="true" />
</bean> 
    
  • 여기서 클래스 내부에 또 다른 클래스가 존재하는 클래스(inner class)퍼럼 bean클래스 자체를 안에 넣을수 있다.
  • 밑의 빈을 위에 빈에 넣어준다.
  • 넣으면 넣어지는 빈의 id는 지워준다.

<bean id="moniter3" class="spring5.SystemMoniter" p:periodTime="50">
	<property name="sender">
		<bean  class="spring5.SmsSender">
			<constructor-arg value="true" />
		</bean> 
	</property>
</bean>

List객체

List 컬렉션 객체일때는 list태그를 사용한다
마찬가지로 우선 파일을 순서대로 만들면서 정리하고자 한다.

1. PerformanceMoniter.java 생성 (컬랙션 List)

package spring6;

import java.util.List;
//성능(List객체)
public class PerformanceMoniter {

	private List<Double> number;//성능  =>컬랙션List에 들어가는 자료형은 double

	public void setNumber(List<Double> number) {
		this.number = number;
		System.out.println("setNumber() call=>"+number);
	}
}

2. applicationContext.xml 내용추가

  • id대신 name을 사용해도 된다.
  • list태그로 value를 묶어준다

<bean name="PerformanceMoniter" class="spring6.PerformanceMoniter"
			scope="prototype">
			
	<property name="number">
		<list>
			<value>0.2</value>
			<value>0.3</value>
		</list>
	</property>
</bean>

3.Main.java 생성

  • 2.5방식을 3.x방식으로 바꿔서 형변환을 수정한다.

package spring6;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//1.메모리관리->xml파일이 여러개->배열로 관리->파일명부여  // xml이 여러개면 ,로 쭉쭉 나열 가능
			String [] configLocation=new String[] {"applicationContext.xml"};	
		//2.xml파일을 메모리에 올려줄 수 있는 클래스를 통해서 객체를 생성
			AbstractApplicationContext context=
					new ClassPathXmlApplicationContext(configLocation);
		//3.자바프로그램이 종료->자동적으로 context객체도 같이 종료 설정	
			context.registerShutdownHook();
		//4.xml에서 만들어진 객체를 가져와서 처리	
		//spring 2.5방식(객체를 가져오고나서 원하는 자료형으로 형변환시켜서 사용)
		//	->spring3.x~spring 5.x	(처음부터 형변환시켜서 객체를 가져오는 방식)
		/*	 2.5방식
			PerformanceMoniter moniter=(PerformanceMoniter)context.getBean("PerformanceMoniter");
		*/
			//3.x 방식 형식) ~getBean("의존성객체를 얻어올id",형변환을 할 클래스명.class)
			PerformanceMoniter moniter=
					context.getBean("PerformanceMoniter",PerformanceMoniter.class);
			
			PerformanceMoniter moniter2=
					context.getBean("PerformanceMoniter",PerformanceMoniter.class);
			
			PerformanceMoniter moniter3=
					context.getBean("PerformanceMoniter",PerformanceMoniter.class);
			
			System.out.println("moniter=>"+moniter);//SmsSender
			System.out.println("moniter2=>"+moniter2);//SmsSender
			System.out.println("moniter3=>"+moniter3);//SmsSender
			System.out.println("moniter2==moniter3=>"+(moniter2==moniter3));
		//5.context도 종료
			context.close();//메모리에 올려놓은 모든 빈즈객체->메모리해제
	}

}



Set객체

Set 컬렉션 객체일때는 set태그를 사용한다
마찬가지로 우선 파일을 순서대로 만들면서 정리하고자 한다.

  • Set컬랙션 객체=> 중복 값을 허용하지 않는 집합객체를 사용할때 사용

1. Customer.java 생성 (컬랙션 Set)


package spring7;

import java.util.Set;

//고객,도서(서버에 접속->ip주소(=도메인이름),접속시간(Propertie에서)
//책대여수

public class Customer {
	private Set<Integer> subSet;//책대여수(중복 X)
	//Set인경우 xml에서 어떻게 환경설정?-> <set>태그사용

	public void setSubSet(Set<Integer> subSet) {
		this.subSet = subSet;
		System.out.println("setSubSet call");
	}
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "Customer[subSet="+subSet+"]";
	}
}

2. applicationContext.xml 내용추가

  • set으로 값(value)을 묶어준다

<bean name="customer" class="spring7.Customer">
	<property name="subSet">
		<set>
			<value>1</value>
			<value>4</value>
		</set>
	</property>
</bean>


3. Main.java 생성

  • 이전꺼에서 id값과 형변환 할 클래스만 수정한다.

package spring7;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//1.메모리관리->xml파일이 여러개->배열로 관리->파일명부여  // xml이 여러개면 ,로 쭉쭉 나열 가능
			String [] configLocation=new String[] {"applicationContext.xml"};	
		//2.xml파일을 메모리에 올려줄 수 있는 클래스를 통해서 객체를 생성
			AbstractApplicationContext context=
					new ClassPathXmlApplicationContext(configLocation);
		//3.자바프로그램이 종료->자동적으로 context객체도 같이 종료 설정	
			context.registerShutdownHook();
		//4.xml에서 만들어진 객체를 가져와서 처리	
		//spring 2.5방식(객체를 가져오고나서 원하는 자료형으로 형변환시켜서 사용)
		//	->spring3.x~spring 5.x	(처음부터 형변환시켜서 객체를 가져오는 방식)
		/*	 2.5방식
			PerformanceMoniter moniter=(PerformanceMoniter)context.getBean("PerformanceMoniter");
		*/
			//3.x 방식 형식) ~getBean("의존성객체를 얻어올id",형변환을 할 클래스명.class)
			Customer customer=
					context.getBean("customer",Customer.class);
			
			System.out.println("customer=>"+customer);
			
		//5.context도 종료
			context.close();//메모리에 올려놓은 모든 빈즈객체->메모리해제
	}

}


Map객체

Map 컬렉션 객체일때는 map태그를 사용한다
마찬가지로 우선 파일을 순서대로 만들면서 정리하고자 한다.

  • Map컬랙션 객체=> 특정 key로 데이터를 등록하고 사용할 때 사용

  1. ProtocolHanderFactory.java 생성 (컬랙션 Map)
  • 이 안에 클래스를 2개 더 추가로 넣어준다.
    => class RestHandler, class SoapHandler

package spring9;

import java.util.Map;

class RestHandler{ //자바스크립트의 var RestHandler={}와 같음
	//new RestHandler()->public RestHandler(){} 기본생성자 호출
}

class SoapHandler{}

public class ProtocolHanderFactory {
	//Map객체->HashMap,Hashtable
	private Map<String,Object> map;

	public void setMap(Map<String, Object> map) {
		this.map = map;
		System.out.println("setMap call=>"+map);
	}
	
}

2. applicationContext.xml 내용추가

  • map태그 안에 entry로 묶고 그 안에 키,값을 넣는다
  • 위에서 추가로 만든 클래스들도 빈을 만들고 ref로 연결한다.

<bean name="protocolHanderFactory" class="spring9.ProtocolHanderFactory">
	
	<property name="map">
		<map>
			<entry>
				<key><value>soap</value></key>
				<ref bean="soapHandler" />
			</entry>
			<entry>
				<key><value>rest</value></key>
				<ref bean="restHandler" />
			</entry>
		</map>
	</property>
</bean>

<bean name="soapHandler" class="spring9.SoapHandler" />
<bean name="restHandler" class="spring9.RestHandler" />

</beans>

3. Main 생성

  • 이전꺼에서 id값과 형변환 할 클래스만 수정한다.

package spring9;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//1.메모리관리->xml파일이 여러개->배열로 관리->파일명부여  // xml이 여러개면 ,로 쭉쭉 나열 가능
			String [] configLocation=new String[] {"applicationContext.xml"};	
		//2.xml파일을 메모리에 올려줄 수 있는 클래스를 통해서 객체를 생성
			AbstractApplicationContext context=
					new ClassPathXmlApplicationContext(configLocation);
		//3.자바프로그램이 종료->자동적으로 context객체도 같이 종료 설정	
			context.registerShutdownHook();
		//4.xml에서 만들어진 객체를 가져와서 처리	
		//spring 2.5방식(객체를 가져오고나서 원하는 자료형으로 형변환시켜서 사용)
		//	->spring3.x~spring 5.x	(처음부터 형변환시켜서 객체를 가져오는 방식)
		
			//형식) ~getBean("의존성객체를 얻어올id",형변환을 할 클래스명.class)
			ProtocolHanderFactory factory=
					context.getBean("protocolHanderFactory",ProtocolHanderFactory.class);
			//{soap=spring9.SoapHandler@3ee37e5a, rest=spring9.RestHandler@2ea41516}
			System.out.println("factory=>"+factory);
			
		//5.context도 종료
			context.close();//메모리에 올려놓은 모든 빈즈객체->메모리해제
	}

}


Properties객체

Properties 컬렉션 객체일때는 Props태그를 사용한다
마찬가지로 우선 파일을 순서대로 만들면서 정리하고자 한다.

  • Properties컬랙션 객체=> key=value형태의 데이터를 등록하고 사용할 때 사용

1. BookClient.java (컬랙션 Properties)

  • 서버에 접속=>ip주소,접속시간제한 설정=>Properties객체

package spring8;

import java.util.Properties;

//서버에 접속=>ip주소,접속시간제한 설정=>Properties객체
public class BookClient {

	private Properties Prop;

	public void setProp(Properties prop) {
		this.Prop = prop;
		System.out.println("setProps() call=>"+prop);
	}
	
}

2. applicationContext.xml 내용추가

  • props태그로 묶어준다.
  • 그안에 < prop key="키명" >설정값< /prop>
    => key=value형태의 데이터일경우 value 대신 사용

<bean name="bookClient" class="spring8.BookClient">
	<property name="prop">
		<props>
			<prop key="server">192.168.0.5</prop>
			<prop key="connectionTime">5000</prop>
			<prop key="Retry">3</prop>
		</props>
	</property>
</bean>

3. Main 생성

  • 이전꺼에서 id값과 형변환 할 클래스만 수정한다.

package spring8;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//1.메모리관리->xml파일이 여러개->배열로 관리->파일명부여  // xml이 여러개면 ,로 쭉쭉 나열 가능
			String [] configLocation=new String[] {"applicationContext.xml"};	
		//2.xml파일을 메모리에 올려줄 수 있는 클래스를 통해서 객체를 생성
			AbstractApplicationContext context=
					new ClassPathXmlApplicationContext(configLocation);
		//3.자바프로그램이 종료->자동적으로 context객체도 같이 종료 설정	
			context.registerShutdownHook();
		//4.xml에서 만들어진 객체를 가져와서 처리	
		//spring 2.5방식(객체를 가져오고나서 원하는 자료형으로 형변환시켜서 사용)
		//	->spring3.x~spring 5.x	(처음부터 형변환시켜서 객체를 가져오는 방식)
		/*	 2.5방식
			PerformanceMoniter moniter=(PerformanceMoniter)context.getBean("PerformanceMoniter");
		*/
			//3.x 방식 형식) ~getBean("의존성객체를 얻어올id",형변환을 할 클래스명.class)
			BookClient book=
					context.getBean("bookClient",BookClient.class);
			//{server=192.168.0.5, Retry=3, connectionTime=5000}
			System.out.println("book=>"+book);
			
		//5.context도 종료
			context.close();//메모리에 올려놓은 모든 빈즈객체->메모리해제
	}

}


2022-08-19

0개의 댓글