6. IoC예제(Constructor Injection)
:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
이번에는 또 다른 의존성 주입의 방법인 생성자 주입에 대해 알아보도록 한다.
ConstructHelloController.java
package spring.ex1;
ConstructHelloController.java
package spring.ex1;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
import org.springframework.web.servlet.mvc.AbstractController;
public class ConstructHelloController extends AbstractController{
private HelloBean helloBean;
public ConstructHelloController(HelloBean helloBean){
this.helloBean = helloBean;
}
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception{
ModelAndView mav = new ModelAndView();
mav.setViewName("hello");
mav.addObject("greeting",helloBean.getGreeting());
return mav;
}
}
이번 예제에서도 Bean interface는 HelloBean을 그대로 사용한다.
setter를 통한 주입과 비교해 크게 바뀐 것은 없다. 다만, HelloBean을 매개 변수로 받는 메서드가
setter 메서드에서 생성자 메서드로 바뀌었다는 점이 달라졌다.
dispatcher-servlet.xml
<beans>
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="helloBean" class="spring.ex1.HelloBeanImpl" />
<bean id="helloBean2" class="spring.ex1.HelloBeanImpl2" />
<bean name="/hello.htm" class="spring.ex1.HelloController">
<property name="helloBean" ref="helloBean2" />
</bean>
<bean name="/ConHello.htm" class="spring.ex1.ConstructHelloController">
<constructor-arg ref="helloBean" />
</bean>
</beans>
dispatcher-servlet.xml에 추가된 bean은 이번에 추가한 ConstructHelloController 클래스이다.다만 xml에 주입을 해주는 노드가 property가 아닌 constructor-arg로 바뀐 것을 알 수 있다. 자, 이제 결과를 보여줄 JSP를 만들어 준다.
ConHello.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<b>${greeting }</b>
</body>
</html>
bean의 이름을 다르게 하기 위해 파일을 새로 만들었지만, 내용은 hello.jsp와 같다는 것을 알수 있다.이제 결과를 보도록 한다.
http://localhost:8080/SpringEx/ConHello.htm
private HelloBean helloBean;
public ConstructHelloController(HelloBean helloBean){
this.helloBean = helloBean;
}
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception{
ModelAndView mav = new ModelAndView();
mav.setViewName("hello");
mav.addObject("greeting",helloBean.getGreeting());
return mav;
}
}
이번 예제에서도 Bean interface는 HelloBean을 그대로 사용한다.
setter를 통한 주입과 비교해 크게 바뀐 것은 없다. 다만, HelloBean을 매개 변수로 받는 메서드가
setter 메서드에서 생성자 메서드로 바뀌었다는 점이 달라졌다.
dispatcher-servlet.xml
<beans>
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="helloBean" class="spring.ex1.HelloBeanImpl" />
<bean id="helloBean2" class="spring.ex1.HelloBeanImpl2" />
<bean name="/hello.htm" class="spring.ex1.HelloController">
<property name="helloBean" ref="helloBean2" />
</bean>
<bean name="/ConHello.htm" class="spring.ex1.ConstructHelloController">
<constructor-arg ref="helloBean" />
</bean>
</beans>
dispatcher-servlet.xml에 추가된 bean은 이번에 추가한 ConstructHelloController 클래스이다.다만 xml에 주입을 해주는 노드가 property가 아닌 constructor-arg로 바뀐 것을 알 수 있다. 자, 이제 결과를 보여줄 JSP를 만들어 준다.
ConHello.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<b>${greeting }</b>
</body>
</html>
bean의 이름을 다르게 하기 위해 파일을 새로 만들었지만, 내용은 hello.jsp와 같다는 것을 알수 있다.이제 결과를 보도록 한다.
http://localhost:8080/SpringEx/ConHello.htm
:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />
무언가 다른 결과를 기대했다면 실망 스럽겠지만 결과는 hello.htm 빈을 사용 했을 때와 같다. 이유는 같은 bean을 주입 하였기 때문이다.
보다 시피 생성자 주입과 setter 주입의 결과는 크게 다르지 않다. 다만, 코딩 방식의 차이가 있을 뿐이다.
보다 시피 생성자 주입과 setter 주입의 결과는 크게 다르지 않다. 다만, 코딩 방식의 차이가 있을 뿐이다.
이번에는 생성자 주입으로 보다 소스를 간결히 하는 방법에 대해 간결히 알아보겠다.
HelloBean2.java
package spring.ex1;
public interface HelloBean2 {
public String getGreeting();
}
위와 같이 interface를 생성하였다. 이제 이 interface를 구현하는 class를 생성한다.
HelloBeanImpl2
package spring.ex1;
public String getGreeting();
}
위와 같이 interface를 생성하였다. 이제 이 interface를 구현하는 class를 생성한다.
HelloBeanImpl2
package spring.ex1;
public class HelloBeanImpl2 implements HelloBean2 {
public String getGreeting(){
return "Nice to meet you!!";
}
}
public String getGreeting(){
return "Nice to meet you!!";
}
}
HelloBeanImpl class는 지난번 예제에서 사용한 class를 수정하여 사용한다. 중요한점은 이번에 구현
하는 interface는 HelloBean2 라는 점이다.
ConstructHelloController.java
package spring.ex1;
하는 interface는 HelloBean2 라는 점이다.
ConstructHelloController.java
package spring.ex1;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
import org.springframework.web.servlet.mvc.AbstractController;
public class ConstructHelloController extends AbstractController{
private HelloBean helloBean;
private HelloBean2 helloBean2;
public ConstructHelloController(HelloBean helloBean, HelloBean2 helloBean2){
this.helloBean = helloBean;
this.helloBean2 = helloBean2;
}
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception{
ModelAndView mav = new ModelAndView();
mav.setViewName("ConHello");
mav.addObject("greeting",helloBean.getGreeting());
mav.addObject("greeting2", helloBean2.getGreeting());
return mav;
}
}
Controller는 위와 같이 수정한다. 생성자의 매개변수를 위와 같이 HelloBean2형으로 추가 하였고,
helloBean과 같이 helloBean2에 관한 매개변수와 레퍼런스를 대입한다.이제 dipatcher-servlet.xml을 수정한다.
dispatcher-servlet.xml
<beans>
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="helloBean" class="spring.ex1.HelloBeanImpl" />
<bean id="helloBean2" class="spring.ex1.HelloBeanImpl2" />
<!-- bean name="/hello.htm" class="spring.ex1.HelloController">
<property name="helloBean" ref="helloBean2" />
</bean -->
<bean name="/ConHello.htm" class="spring.ex1.ConstructHelloController">
<constructor-arg ref="helloBean" type="spring.ex1.HelloBean" />
<constructor-arg ref="helloBean2" type="spring.ex1.HelloBean2" />
</bean>
</beans>
생성자 주입 노드를 추가하여 helloBean2를 추가 주입 하였고, type 이라는 속성을 추가 하였다.
이는 helloBean들을 주입할 실제 interface타입을 지정하였고, 생성자를 통한 주입이 2개 이상이더라도
같은 타입의 bean이 아니라면 spring이 기본적으로 type을 잡아주지만, 가급적이면 지정해 주는 것이
좋기 때문에 위와 같이 type을 각각의 interface에 지정하였다.
여기서 또 한가지 주의 깊게 볼 점은 /hello.htm bean을 주석 처리 한 것인대, helloBean2의 JAVA
CLASS에서 구현하는 interface를 HelloBean 에서 HelloBean2로 수정 하였기 때문에 만약 가만히
놔둔 상태로 서버를 실행하면 서로 맞지 않은 타입에 빈을 주입하려 하기 때문에 예외가 발생하게 된다.
Spring은 서버가 올라갈 때에 bean 생성시 예외가 발생하게 되면 다른 bean들도 사용할 수 없기 때문에
bean을 생성할 때는 항상 주의 해야 한다.
ConHello.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<b>${greeting }</b><br>
<b>${greeting2 }</b>
</body>
</html>
JSP에서는 mav.addObject에 추가한 greeting2를 추가한다.
private HelloBean helloBean;
private HelloBean2 helloBean2;
public ConstructHelloController(HelloBean helloBean, HelloBean2 helloBean2){
this.helloBean = helloBean;
this.helloBean2 = helloBean2;
}
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response) throws Exception{
ModelAndView mav = new ModelAndView();
mav.setViewName("ConHello");
mav.addObject("greeting",helloBean.getGreeting());
mav.addObject("greeting2", helloBean2.getGreeting());
return mav;
}
}
Controller는 위와 같이 수정한다. 생성자의 매개변수를 위와 같이 HelloBean2형으로 추가 하였고,
helloBean과 같이 helloBean2에 관한 매개변수와 레퍼런스를 대입한다.이제 dipatcher-servlet.xml을 수정한다.
dispatcher-servlet.xml
<beans>
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="helloBean" class="spring.ex1.HelloBeanImpl" />
<bean id="helloBean2" class="spring.ex1.HelloBeanImpl2" />
<!-- bean name="/hello.htm" class="spring.ex1.HelloController">
<property name="helloBean" ref="helloBean2" />
</bean -->
<bean name="/ConHello.htm" class="spring.ex1.ConstructHelloController">
<constructor-arg ref="helloBean" type="spring.ex1.HelloBean" />
<constructor-arg ref="helloBean2" type="spring.ex1.HelloBean2" />
</bean>
</beans>
생성자 주입 노드를 추가하여 helloBean2를 추가 주입 하였고, type 이라는 속성을 추가 하였다.
이는 helloBean들을 주입할 실제 interface타입을 지정하였고, 생성자를 통한 주입이 2개 이상이더라도
같은 타입의 bean이 아니라면 spring이 기본적으로 type을 잡아주지만, 가급적이면 지정해 주는 것이
좋기 때문에 위와 같이 type을 각각의 interface에 지정하였다.
여기서 또 한가지 주의 깊게 볼 점은 /hello.htm bean을 주석 처리 한 것인대, helloBean2의 JAVA
CLASS에서 구현하는 interface를 HelloBean 에서 HelloBean2로 수정 하였기 때문에 만약 가만히
놔둔 상태로 서버를 실행하면 서로 맞지 않은 타입에 빈을 주입하려 하기 때문에 예외가 발생하게 된다.
Spring은 서버가 올라갈 때에 bean 생성시 예외가 발생하게 되면 다른 bean들도 사용할 수 없기 때문에
bean을 생성할 때는 항상 주의 해야 한다.
ConHello.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<b>${greeting }</b><br>
<b>${greeting2 }</b>
</body>
</html>
JSP에서는 mav.addObject에 추가한 greeting2를 추가한다.
새로이 추가된 Nice to meet you!! 가 출력되었다.
생성자 주입의 장점은 위와 같이 새로운 bean을 추가할때 새로운 setter 메서드를 추가할 필요로 하지않고, 매개변수를 추가해주면 될 뿐이다.
물론 이런 방식보다 명시적으로 setter 메서드를 추가하는 것을 선호하는 개발자도 있다.(사실 더 많다.)
생성자 주입의 장점은 위와 같이 새로운 bean을 추가할때 새로운 setter 메서드를 추가할 필요로 하지않고, 매개변수를 추가해주면 될 뿐이다.
물론 이런 방식보다 명시적으로 setter 메서드를 추가하는 것을 선호하는 개발자도 있다.(사실 더 많다.)
setter 주입을 사용하느냐, 생성자 주입을 사용하느냐는 서로 코딩 타입에 따라 뭐가 좋다 뭐가 나쁘다 할 수는 없는 것이기 때문에 여러분의 선택에 따라 좋은 방법을 선택하길 바란다.
기업100%환급/오라클/자바/스프링/안드로이드/닷넷C#/웹퍼블리싱… | 12-27 | 2250 | ||
[채용예정교육]오라클자바개발잘하는신입뽑기2개월과정,교육전취… | 12-11 | 1617 | ||
53 | [평일주간100%환급]Spring,JAVA,JSP,안드로이드,C#닷넷,SQL,튜닝… | 03-15 | 1411 | |
52 | [주말]C#,ASP.NET마스터 | 01-31 | 1530 | |
51 | [기업100%환급,평일주간]SQL기초에서스키마오브젝트,PLSQL,힌트… | 01-31 | 1768 | |
50 | [기업100%환급]개발자를위한스프링,마이바티스,하이버네이트(스… | 01-31 | 1219 | |
49 | [평일주간,평일야간,주말]Spring,MyBatis,Hibernate개발자과정 | 01-19 | 1512 | |
48 | [평일주간,평일야간,주말]안드로이드개발자과정 | 01-11 | 1343 | |
47 | [평일야간,주말주간,주말야간]JAVA,Network&JSP&Spring,MyBatis,… | 01-03 | 1879 | |
46 | 기업100%환급/오라클/자바/스프링/안드로이드/닷넷C#/웹퍼블리싱… | 12-27 | 2250 | |
45 | [기업100%환급]자바웹개발기초과정(JAVA,JDBC,JSP,Servlet,Aajx,… | 12-19 | 1617 | |
44 | [평일주간야간, 주말]웹퍼블리싱 마스터(HTML5,CSS3,jQUERY,AJAX… | 12-14 | 1588 | |
43 | [채용예정교육]오라클자바개발잘하는신입뽑기2개월과정,교육전취… | 12-11 | 1617 | |
42 | [주말주간]자바&웹,jQUERY,스프링프레임워크 | 12-09 | 1291 | |
41 | [평일야간]닷넷(C#,Network,ADO.NET,ASP.NET)마스터 | 12-01 | 1511 | |
40 | [기업100%환급]자바기초&안드로이드개발자과정(Android전액환급… | 12-01 | 1693 | |
39 | [평일야간,주말]SQL기초에서실무까지(SQL기초,PLSQL,힌트,튜닝) | 12-01 | 1162 |
댓글 없음:
댓글 쓰기