Spring Constructor DI (value 주입)
- 프로그래밍/Spring FWK
- 2015. 12. 13. 17:46
Constructor DI (value직접주입)
생성자 주입에 관한 이전예제는 DI target이 bean으로 ref-bean 주입 방식이였다. 이번에는 String, int 등의 값을 직접 주입하는 방법이나, 생성자가 두 개 있는 경우 이를 어떻게 구분하는지에 대해서 알아보고자 한다. 이번 포스팅 부터 예제는 새로운 예제로 작성하여 가급적 전체 소스를 올리려고 한다.
XML방법
<value> 태그 사용
* bean을 주입하는 경우는 <ref bean="">를 사용
12345 <bean id="messageProvider" class="com.ljs.message.provider.DefaultMessageProvider"><constructor-arg><value>Spring Constructor Value DI Test</value></constructor-arg></bean>cs
[Interface IMessageProvider]
1 2 3 4 5 | package com.ljs.message.provider; public interface IMessageProvider { public String getMessage(); } | cs |
[class DefalutMessageProvider]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package com.ljs.message.provider; public class DefaultMessageProvider implements IMessageProvider { private String message; public DefaultMessageProvider(String message) { this.message = message; } @Override public String getMessage() { return this.message; } } | cs |
[class Main]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package com.ljs.message; import org.springframework.context.support.GenericXmlApplicationContext; import com.ljs.message.provider.IMessageProvider; public class ApplicationMain { public static void main(String[] args) { // ApplicationContext 부트스트랩 GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(); ctx.load("classpath:META-INF/spring/app-context-annotation.xml"); ctx.refresh(); // bean use IMessageProvider provider = (IMessageProvider) ctx.getBean("messageProvider"); System.out.println(provider.getMessage()); ctx.close(); } } | cs |
[app-context-xml.xml]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?xml version="1.0" encoding="UTF-8"?> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans <bean id="messageProvider" class="com.ljs.message.provider.DefaultMessageProvider"> <constructor-arg> <value>Spring Constructor Value DI Test</value> </constructor-arg> </bean> </beans> | cs |
Annotation방법
* 나머지 소스는 상동
생성자 파라메터에 @Autowired와 @Value 어노테이션 사용
* Autowired 되어야 하기 때문에 아래 메소드가 정의된 클래스에는 @Service 등으로 bean등록이 되어야 함.
1234 @Autowiredpublic DefaultMessageProvider(@Value("Spring Constructor Value DI Test") String message) {this.message = message;}cs
[class DefalutMessageProvider]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package com.ljs.message.provider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @Service("messageProvider") public class DefaultMessageProvider implements IMessageProvider { private String message; @Autowired public DefaultMessageProvider(@Value("Spring Constructor Value DI Test") String message) { this.message = message; } @Override public String getMessage() { return this.message; } } | cs |
[app-context-annotation.xml]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?xml version="1.0" encoding="UTF-8"?> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans <!--스프링이 코드기반에서 의존성 요구조건을 스캔하게끔 세팅--> <context:annotation-config/> <!--스프링이 코드에서 지정된 패키지(및 하위)아래에 있는 주입 가능한 빈을 모두 스캔하도록 세팅--> <context:component-scan base-package="com.ljs.message"/> </beans> | cs |
여지까지 기본적은 constructor을 이용한 value 대입 방법이다.
하지만 annotation방식에서는 소스코드에 하드코딩으로 메시지 내용이 포함되어 있어 추후 관리에 어려움이 예상된다. 또한 생성자가 두 개인 경우 어느 생성자로 Injection될 지 지정하는 방법을 아래에서 더 알아보자. 아래는 위에 소스를 기준으로 일부만 변경하도록 한다.
Annotation방식에서 Value("Spring Constructor Value DI Test") 하드코딩 문제 해결
app-context-annotation.xml에 String bean 정의
1234567 <!--스프링이 코드기반에서 의존성 요구조건을 스캔하게끔 세팅--><context:annotation-config/><!--스프링이 코드에서 지정된 패키지(및 하위)아래에 있는 주입 가능한 빈을 모두 스캔하도록 세팅--><context:component-scan base-package="com.ljs.message"/><bean id="message" class="java.lang.String" c:_0="Spring Constructor Value DI Test"/>cs * String 객체를 만들어 injection 한다. c:_0은 String객체를 만들 때 첫번째(0) 생성자로 "" 값을 넘겨준다는 의미
@Service로 등록된 클래스 @Autowired 된 생성자에 @Value 제거
1234 @Autowiredpublic DefaultMessageProvider(@Value("Spring Constructor Value DI Test")String message) {this.message = message;}cs
위와같이 지정이 되면, @Service로 등록된 bean을 생성할 때, @Autowired 생성자에 파라메터로 bean(id="message")인 String 객체를 전달한다.
그리하여 소스코드에 있는 @Value는 더이상 불필요하고 소스와 메시지를 분리 할 수 있게 된다.
생성자혼동
동일한 파라메터의 명이지만, 다른 타입으로 생성자가 생성되어 있는 경우 어디에 DI가 수행될지 판단이 어려울 때가 있다. 아래는 똑같은 message라는 파라메터를 받지만, 생성자 마다 String으로, int로 구현되어 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package com.ljs.message.provider; public class DefaultMessageProvider implements IMessageProvider { private String message; public DefaultMessageProvider(String message) { this.message = message; System.out.println("String 생성자로 수행"); } public DefaultMessageProvider(int message) { this.message = Integer.toString(message); System.out.println("int 생성자로 수행"); } @Override public String getMessage() { return this.message; } } | cs |
생성자혼동(XML)
기본적으로 xml에 정의된 <value>의 값은 String으로 인식한다. 그래서 위에 상황에서는 String message를 파라메터로 받는 생성자가 수행되게 된다.
만약, int 파라메터를 받는 생성자를 수행하고자 한다면 아래와 <constructor-arg>에 타입을 지정하면 된다.
생성자 타입 명시적 지정 <constructor-arg type="int">
12345 <bean id="messageProvider" class="com.ljs.message.provider.DefaultMessageProvider"><constructor-arg type="int"><value>1000</value></constructor-arg></bean>cs\
생성자혼동(Annotation)
어노테이션 방식은 문제해결이 간단하다. @Autowired 어노테이션은 생성자 메서드 중 단 한곳에만 적용할 수 있다. 그렇지 않으면 ApplicationContext 부트스트랩 과정에서 에러가 발생한다.
@Autowired는 생성자 중 한 곳에만 쓸 수 있다.
- 그래서 생성자 혼동에 관련 된 혼동은 애초에 없다.
- 사실, xml방식도 굳이 저렇게 구현하는 패턴은 없을 것 같지만
12345678 public DefaultMessageProvider(String message) {this.message = message;}@Autowiredpublic DefaultMessageProvider(@Value("100") int message) {this.message = Integer.toString(message);}cs
* 수행결과
'프로그래밍 > Spring FWK' 카테고리의 다른 글
Spring Non Singletone (0) | 2015.12.14 |
---|---|
Spring Collection (List, Map, Properties, Set) 주입 (0) | 2015.12.13 |
Spring 다중 applicationContext 중첩사용 (0) | 2015.12.13 |
Spring SpEL을 이용하여 Value세팅하기 (0) | 2015.12.13 |
Spring Constructor DI (ref bean주입) (0) | 2015.12.13 |
Spring Setter DI (0) | 2015.12.13 |
Spring Bean생성 XML, Annotation예제 (0) | 2015.12.13 |
IoC in Spring : ApplicationContext (0) | 2015.12.13 |
이 글을 공유하기