Spring Setter DI
- 프로그래밍/Spring FWK
- 2015. 12. 13. 17:39
Setter Injection
이전 예제는 messageRender객체는 messageProvider를 property로 갖는 구조였다. 이를 위해서 main클래스는 messageRender객체를 획득하고,messageProvider객체를 획득하여 messageRender에 messageProvider를 setting하여 주었다. Setter DI를 이용하면 보다 간편하게 이를 처리할 수 있다. main에서는 별도로 messageProvider를 생성하지 않아도 된다. Spring에서 messageRender객체를 생성할 때 property인 messageProvider를 자동으로 생성하여 주입하여준다. 때문에 별도의 messageProvider생성에 대한 소스코드는 불필요 함으로 의존성을 감소와 동시에 소스코드를 간결하게 작성할 수 있다.
적용방법(xml) : 1번과 2번 둘 중 하나를 선택하여 적용하면 된다.
1) <bean>태그 하위에 <property>를 지정
12345 <bean id="messageRender" name="" class= "com.ljs.message.render.DefaultMessageRender"><property name="messageProvider"><ref bean="messageProviderBean"/></property></bean>cs 2) <bean>태그에 p:propertyName-ref="beanID"를 추가(Spring 2.5 이상)
12 <bean id="messageRender" name="" class= "com.ljs.message.render.DefaultMessageRender"p:messageProvider-ref="messageProviderBean"/>
- xmlns:p="http://www.springframework.org/schema/p" 스키마 추가 필요
적용방법(Annotation) : @Autowired 혹은 @Resource(name="propertyName")
1) bean으로 관리 될 class에 @Service
123 @Service("messageProvider")public class DefaultMessageProvider implements IMessageProvider {...cs
2) bean을 갖게 될 class setter 메소드에 @Autowired
12345678910111213 @Service("messageRender")public class DefaultMessageRender implements IMessageRender {private IMessageProvider messageProvider;...@Autowired@Overridepublic void setMessageProvider(IMessageProvider provider) {this.messageProvider = provider;}...}cs
변수에 직접 @Autowired 하는 경우 setter 메소드도 정의할 필요가 없다.
12345678 @Service("messageRender")public class DefaultMessageRender implements IMessageRender {@Autowiredprivate IMessageProvider messageProvider;...}cs
혹은 @Resource
12345678910111213 @Service("messageRender")public class DefaultMessageRender implements IMessageRender {private IMessageProvider messageProvider;...@Resource(name="messageProvider")@Overridepublic void setMessageProvider(IMessageProvider provider) {this.messageProvider = provider;}...}cs
소스코드는 이전예제와 동일하기 때문에 달라지는 부분만 설명.
1. Spring XML 방식 Setter Injection
[main class]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | package com.ljs.message; import org.springframework.context.support.GenericXmlApplicationContext; import com.ljs.message.render.IMessageRender; public class AppCtxTestMain { public static void main(String[] args) { // ApplicationContext 부트스트랩 GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(); ctx.load("classpath:META-INF/spring/app-context-xml.xml"); ctx.refresh(); // ApplicationContext로 부터 bean 획득 IMessageRender render = (IMessageRender) ctx.getBean("messageRender"); /* IMessageProvider provider = (IMessageProvider) ctx.getBean("messageProvider"); render.setMessageProvider(provider); */ render.render(); } } | cs |
Setter대상이 되는 DI 타겟 객체는 더이상 직접 생성할 필요가 없기 때문에 주석처리 하였다
class diaram을 보면 messageProvider와 의존성이 없어졌음을 알 수 있다.
[app-context-xml.xml]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <?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 <!-- ApplicationContext에서 관리 할 bean 정의 --> <bean id="messageProviderBean" name="" class= "com.ljs.message.provider.DefaultMessageProvider"/> <!-- 아래 두 가지 방법 중 1개 적용 --> <!-- preperty 태그이용 --> <bean id="messageRender" name="" class= "com.ljs.message.render.DefaultMessageRender"> <property name="messageProvider"> <ref bean="messageProviderBean"/> </property> </bean> <!-- p 스키마 이용 <bean id="messageRender" name="" class= "com.ljs.message.render.DefaultMessageRender" p:messageProvider-ref="messageProviderBean"/> --> </beans> | cs |
bean태그 하위에 property태그를 삽입하여 messageProvider라는 property는 messageProviderBean이라는 id로 생성된 bean을 주입할 것을 명시하였다.
아래에 있는 p스키마를 이용하는 방법도 동일한 방법이다. 대신 p스키마 이용은 상단 네임스페이스에 xmlns:p 를 정의하여 주고 2.5버젼 이상에서 사용가능 하다.
2. Spring Annotation 방식 Setter Injection
[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 23 24 | <?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 |
(변경사항 없음)
스프링이 스캔하여 bean을 관리할 component pakage를 지정하는 설정.
[class DefaultMessageProvider]
1 2 3 4 5 6 7 8 9 10 11 | package com.ljs.message.provider; import org.springframework.stereotype.Service; @Service("messageProvider") public class DefaultMessageProvider implements IMessageProvider { @Override public String getMessage() { return "Hell World!"; } } | cs |
(변경사항 없음)
현재 클래스가 Sping에서 "messageProvider" 라는 id로 관리될 것을 명시하고,
[class DefaultMessageRender]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | package com.ljs.message.render; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.ljs.message.provider.IMessageProvider; @Service("messageRender") public class DefaultMessageRender implements IMessageRender { private IMessageProvider messageProvider; @Override public void render() { if(messageProvider==null) { throw new RuntimeException("messageProvider can't be null"); } else { System.out.print(messageProvider.getMessage()); } } @Autowired @Override public void setMessageProvider(IMessageProvider provider) { this.messageProvider = provider; } @Override public IMessageProvider getMessageProvider() { return messageProvider; } } | cs |
(25라인 어노테이션 추가)
위에 정의한 bean을 has a로 가지고 있는 클래스 세터에 @Autowired 키워드를 추가하면 자동으로 객체를 생성하여 주입해 준다.
[main class]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | package com.ljs.message; import org.springframework.context.support.GenericXmlApplicationContext; import com.ljs.message.provider.IMessageProvider; import com.ljs.message.render.IMessageRender; public class AppCtxTestMain { public static void main(String[] args) { // ApplicationContext 부트스트랩 GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(); ctx.load("classpath:META-INF/spring/app-context-annotation.xml"); ctx.refresh(); // ApplicationContext로 부터 bean 획득 IMessageRender render = (IMessageRender) ctx.getBean("messageRender"); /* IMessageProvider provider = (IMessageProvider) ctx.getBean("messageProvider"); render.setMessageProvider(provider); */ render.render(); } } | cs |
* 참고사항
- @Autowired는 setter 메소드에 붙여 @Service로 등록된 bean을 자동으로 injection처리
- @Autowired를 property 선언에 바로 붙이는 경우 별도의 setter를 생성할 필요 없음
- @Autowired대신에 @Resource(name="beanID")를 통해서 injection 가능.
- @Resource는 jSE와 JEE플랫폼 모두에서 사용할 수 있는 공통 자바 어노테이션을 정의하는 JSR-259표준 어노테이션 중 하나. @Autowired와 달리 미세한 DI조건을 제어할 수 있는 name 파라메터를 지원한다.
- @Resource를 사용하기 위해서는 jsr250.jar 파일을 lib에 추가하여야 한다.
다운로드
'프로그래밍 > Spring FWK' 카테고리의 다른 글
Spring 다중 applicationContext 중첩사용 (0) | 2015.12.13 |
---|---|
Spring SpEL을 이용하여 Value세팅하기 (0) | 2015.12.13 |
Spring Constructor DI (value 주입) (0) | 2015.12.13 |
Spring Constructor DI (ref bean주입) (0) | 2015.12.13 |
Spring Bean생성 XML, Annotation예제 (0) | 2015.12.13 |
IoC in Spring : ApplicationContext (0) | 2015.12.13 |
IoC in Spring : BeanFactory (0) | 2015.12.13 |
Spring IoC (0) | 2015.12.13 |
이 글을 공유하기