티스토리 뷰

Dependency Injection의 타입에는 가장 일반적인 두가지 방법,

Constructor Injection과 Setter Injection이 있다.

지난 게시물에서 Constructor Injection을 다루었고 Setter Injection에 대해 다루어 보겠다.

 

1. Setter Injection

Setter Injection이란 클래스의 setter method를 부름으로써 의존성을 주입시키는 것이다.

 

Development Process 

1) Create setter method in your class for injection

2) Configure the dependency injection in Spring config file.

 

코드예시 : CricketCoach class를 만든 후에 fortuneService 기능을 구현

1) Coach interface implement받는 CricketCoach를 만든 다음에 helper class 또한 지정해준다.(FortuneService class) 

2) Setter method를 생성.

package com.luv2code.springdemo;

public class CricketCoach implements Coach {
	private FortuneService fortuneService;
	
	// create a no-arg constructor
	public CricketCoach() {
		System.out.println("CricketCoach : inside no-arg constructor");
	}
	
	//our setter method -> dependency를 주입했을 때 spring에 의해 불려질 메소드.
	public void setFortuneService(FortuneService fortuneService) {
		System.out.println("CricketCoach : inside setter method - setFortuneService");
		this.fortuneService = fortuneService;
	}
	
		@Override
	public String getDailyWorkout() {
		return "Practice fast bowling for 15 minutes";
	}

	@Override
	public String getDailyFortune() {
		return fortuneService.getFortune();
	}

}

(System.out.println()을 찍어준 이유는 Spring이 바르게 접근했는지를 확인해 주기 위해서이다.)

 

3) Config 파일 설정.

<bean id="myFortuneService"
    	class="com.luv2code.springdemo.HappyFortuneService">
</bean>

 <bean id="myCricketCoach" class="com.luv2code.springdemo.CricketCoach">
    	<!-- set up setter injection -->
    	<property name="fortuneService" ref="myFortuneService"/>
</bean>

위의 Configuration file 설정을 통해 Spring이 뒤에서 해주는 역할은 

HappyFortuneService myFortuneService = new HappyFortuneService();

CricketCoach myCricketCoach = new CricketCoach();

myCricketCoach.setFortuneService(myFortuneService); 로 bean을 생성한다.

 

* <property name="fortuneService" ref="myFortuneService"/>의 역할

일반적으로 어떠한 property name이라도, Spring이 setter method를 부르는것을 시도한다.

property name을 보고 첫 문자를 대문자로 바꾼후에 setter method를 부른다. (setter method와 이름을 맞춰주면 된다)

그리고 ref로 되어 있는 값을 setter method의 매개변수로 넘기는 것이다.

 

4) App을 만들어 Spring container가 만들어준 bean을 회수하여 사용.

package com.luv2code.springdemo;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SetterDemoApp {
	public static void main(String[] args) {
		
		//load the spring configuration file
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		//retrieve bean from spring container
		CricketCoach theCoach = context.getBean("myCricketCoach", CricketCoach.class);
		//myCricketCoach가 xml파일의 id가 같아야함.
		
		//call methods on the bean
		//...let's come back to this..
		System.out.println(theCoach.getDailyWorkout());
		System.out.println(theCoach.getDailyFortune());
		
		// close the context
		context.close();
	}
}

2. Injecting literal values

 이때까지는 FortuneService라는 helper class(dependency)를 CricketCoach에 주입하는 법을 배웠다.

String과 같은 literal value를 주입해보자.

(hard coding으로 하는 법, properties file을 통해 읽어오는 법이 있다)

* literal이란? (constant와 literal의 차이점) 

 constant는 변하지 않는 변수를 의미하며 메모리 값을 변경 할 수 없다. (Java의 final 키워드)

literal이란 변수의 값이 변하지 않는 데이터를 의미한다. String, int, char, boolean 같이 변하지 않는 데이터. 데이터 그 자체를 일겉는다.

 

 

Development Process

1. create setter methods in your class for injection 
2. Create Properites File

3. Load Properties File in Spring config file 

4. Reference values from Properties File

 

 

코드예시 : 이메일과 팀 이름(String)을 주입시키기.

1) private로 필드 만든 다음에 그것을 setter / getter method를 만든다.

package com.luv2code.springdemo;

public class CricketCoach implements Coach {

	//add new fields for emailAddress and team
	private String emailAddress;
	private String team;
	
	// create a no-arg constructor
	public CricketCoach() {
		System.out.println("CricketCoach : inside no-arg constructor");
	}
	
	//getter & setter
	
	public String getEmailAddress() {
		return emailAddress;
	}

	public void setEmailAddress(String emailAddress) {
		System.out.println("CricketCoach : inside setter method - setEmailAddress");
		this.emailAddress = emailAddress;
	}

	public String getTeam() {
		return team;
	}

	public void setTeam(String team) {
		System.out.println("CricketCoach : inside setter method - setTeam");
		this.team = team;
	}
}

 

2) sport.propertiesjunho file(properties file)을 만들어 준다.

foo.email=silly@naver.com
foo.team=Mighty Java Coders

3) Load Properties File in Spring config file &  Reference values from Properties File

<context:property-placeholder location="classpath:sport.propertiesjunho"/>

<bean id="myCricketCoach" class="com.luv2code.springdemo.CricketCoach">
    	<!-- inject literal values -->
    	<property name="emailAddress" value="${foo.email}"/>
    	<property name="team" value="${foo.team}"/>
</bean> 

4) getter method로 app에서 불러오면 된다.

package com.luv2code.springdemo;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SetterDemoApp {
	public static void main(String[] args) {
		
		//load the spring configuration file
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		//retrieve bean from spring container
		CricketCoach theCoach = context.getBean("myCricketCoach", CricketCoach.class)
		
		//call our new methods to get the literal values
		System.out.println(theCoach.getEmailAddress());
		System.out.println(theCoach.getTeam());
		
		// close the context
		context.close();
	}
}

* <context:property-placeholder/> : properties file을 spring 환경에 로딩해주는것.

* value는 literal 값에 사용되고, ref는 다른 objects나 dependencies를 부를때 사용 된다.

* ${the prop name}을 통해서 spring에서 properties file의 value를 불러올수 있다. 

properties file의 name은 아무렇게 지어도 상관 없지만, config file에서 property name을 부르는 것과 spring setup에서 property name을 부르는것에 일관되어야 한다.

* hard-coding으로  ${}대신 String값을 직접 입력 해주어도 되지만 이제 외부 파일에서 읽어 올 수 있게 되었다.

 

* CricketCoach theCoach = context.getBean("myCricketCoach", CricketCoach.class); 에서

bean 회수시 Coach interface가 아닌 CricketCoach class를 사용하는 이유 

Coach interface에는 두개의 method가 있고, CricketCoach class에는 네 가지의 method가 있다.

Coach.class로 설정 시, Coach interface에서 정의된 method만 접근 가능하다. 

CricketCoach.class 설정 시, 모든 method에 접근 가능하다.

요점은 object를 회수하고 할당을 어떻게 하는지에 따라 달려있다.(method에 대한 visibility를 결정하기 때문이다)

 

이때까지 Spring container의 역할 중 하나인 Dependency Injection의 개념에 대해 알아 보았다.

즉, App(Client)가 객체를 직접 생성하지 않고, helper class(dependencies)를 Spring container에 주입시킴으로서 bean을 생성할 수 있도록 설계할 수 있었다. App에서는 코드를 수정 할 필요 없이, Spring이 참조하는 config file만을 수정함으로서 쉽게 데이터, 내용를 변경 할 수 있고, 그렇게 dependencies를 주입시킨 Spring container에서 bean을 생성하도록 outsourcing 하여 직접 코드를 적는 대신 Spring이 생성한 bean을 회수해 간단히 사용 할 수있게 되었다.

최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday