Zero to Hero
Published 2021. 2. 7. 18:44
Spring 02 Programming

Spring 환경에서 Autowired 테스트

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:config/springbeans.xml")
public class HelloBeanSpringTest {
	// BeanFactory factory = new
	// GenericXmlApplicationContext("config/springbeans.xml");
	@Autowired
	Hello hello;
	@Autowired()
	Printer printer;
	// 이건 에러가 난다
	// Printer Bean이 현재 2개 있는데, printer에 어떤 걸 넣어줘야할지 모르겠기 떄문임;

	
	@Autowired
	Hello hello;
	@Autowired()
	Printer strPrinter;
	// 이건 잘 작동한다
	// Bean은 우선 변수 이름이 같은 Bean을 우선적으로 할당한다
	

	@Autowired
	Hello hello;
	@Autowired
	@Qualifier("strPrinter")
	Printer strPrinter;
	// 이건 잘 작동한다
	// 동일 타입의 Bean이 2개 이상 있고, 특정지어줘야할 떄 Qualifier annotaion을 사용하면
	// 으 특정 bean을 주입해준다.

 

package myspring.di.xml.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import junit.framework.Assert;
import myspring.di.xml.Hello;
import myspring.di.xml.Printer;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:config/springbeans.xml")
public class HelloBeanSpringTest {
	// BeanFactory factory = new
	// GenericXmlApplicationContext("config/springbeans.xml");
	@Autowired
	Hello hello;
	@Autowired
	@Qualifier("strPrinter")
	Printer printer;

	@Test
	public void setterInjection() {
		// 더이상 팩토리도 만들고, 팩토리에서 받아서 아래처럼 주입할 필요가 없음
		// Hello hello2 = factory.getBean("hello", Hello.class);
//		Assert.assertEquals("Hello 스프링", hello.sayHello());
		hello.print();
		Assert.assertEquals("Hello 스프링", printer.toString());
		// 저 위에 Autowired한 printer와 hello 생성 시 주입되는 printer가 같다
		// 왜냐면 strPrinter bean은 싱글톤으로 생성되기 때문임
		// 다르게 하고 싶다면 strPrinter에 scope를 prototype으로 해줘야함
		Assert.assertSame(printer, hello.getPrinter());
	}

}

 

@Autowired @Resource 차이

Autowired

Spring에서 사용하는 어노테이션, 정밀한 의존관계 주입에 사용한다.

생성자, setter, method에 다 사용 가능, 기본적으로 type (형)으로 의존성을 주입하고, Qualifier로 특정 지을 수 있다.

 

Resource

Java 진영에서 만듦

Autowired랑 기능은 같은데 반드시 주입하려는 Bean의 이름을 적어줘야 한다.

XML으로 Bean을 관리할 때 장단점

장점

XML은 태그를 이용하기 때문에 계층 구조를 한눈에 볼 수 있다.

 

단점

XML 파일이 여러 개 필요해질 수 있다.

Bean이 많아지면 XML 파일을 관리하기 번거로워질 수 있다.

코드 레벨이 아니라 외부 설정 파일을 사용하는 것이기 때문에 협업 시 충돌이 일어날 가능성이 높다.

 

해결법 중 하나, @Component + <component-scan>

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
	<!-- interface는 객체를 생성할 수 없다, 그래서 등록할 필요가 없음 -->
	
	<!-- Component Scan 을 사용해보자 -->
	<context:component-scan base-package="myspring.di.annot"></context:component-scan>
	<!-- 와우 이걸 쓰니깐 s가 붙음 -->
	
	<!-- String Printer 클래스를 bean으로 등록함 -->
	<bean id="strPrinter" class="myspring.di.xml.StringPrinter">
	</bean>

	<!-- ConsolePrinter Bean 설정 -->
	<bean id="conPrinter" class="myspring.di.xml.ConsolePrinter">
	</bean>
	<!-- Hello Bean 설정 -->
	<!-- scope singleton(default) 객체생성 하나만 prototype 객체 생성 항상 request, session 
		웹에서 사용함, session이 request 보다 scope이 더 넓다 -->
	<bean id="hello" class="myspring.di.xml.Hello" scope="singleton">
		<!-- setter injection 설정 -->
		<property name="name" value="스프링"></property>
		<property name="printer" ref="strPrinter"></property>
	</bean>
	<bean id="helloC" class="myspring.di.xml.Hello" scope="singleton">
		<!-- constructor injection 설정 -->
		<constructor-arg index="0" value="생성자"></constructor-arg>
		<constructor-arg index="1" ref="conPrinter"></constructor-arg>
	</bean>
</beans>

 

Bean을 관리하는 전략

전략 1. XML만을 이용하기 ( ~Spring 2.5)

위에 언급한 문제점이 있음

 

전략 2. Annotation + XML 혼합

@Component + <component-scan>의 조합

 

전략 3, Annotaion Only (Spring boot)

설정은 @Configuration, Bean은 @Bean을 통해 Spring Container에 새로운 Bean 객체를 제공한다.

Bean의 등록 및 의존 관계를 Java 코드만으로 해결한다.

 

Spring MVC

1. MVC 의존성 추가

2. web.xml

DispatcherServlet(Front Controller)을 등록

ContextLoaderListener를 웹 서버(tomcat)의 web.xml에 등록해서 Spring Bean Configuration XML을 웹 서버가 인지할 수 있도록 설정

3. Controller 클래스 작성

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
  <display-name>MySpringMVC</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  <!-- needed for ContextLoaderListener -->
  <!-- tomcat에 beans.xml 을 등록해줌 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:config/springbeans.xml</param-value>
	</context-param>

	<!-- Bootstraps the root web application context before servlet initialization -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
	<servlet>
		<servlet-name>springDispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<!-- web 관련된 설정.xml을 tomcat에 등록해줌 -->
			<!-- param-value 에 넣어주면됨 -->
			<param-value>classpath:config/springbeans.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- Map all requests to the DispatcherServlet for handling -->
	<servlet-mapping>
		<servlet-name>springDispatcherServlet</servlet-name>
		<!-- front controller 역할을 하기 때문에 이 uri 패턴으로 들어오는 요청은 일단 dispatcherservlet에 옴 -->
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>
</web-app>

 

package myspring.user.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import myspring.user.dao.IUserDAO;
import myspring.user.vo.UserVO;

@Controller
public class UserController {
	@Autowired
//	@Qualifier("UserDAOImpl2")
	private IUserDAO dao;

	@RequestMapping("/userList.do")
	public ModelAndView getUserList() {
		List<UserVO> users = dao.getUsers();
		return new ModelAndView("userList.jsp", "users", users);
	}

	@GetMapping("/userDetail.do")
	public String getUser(@RequestParam String userid, Model model) {
		UserVO user = dao.getUser(userid);
		model.addAttribute("userOne", user);
		return "userDetail.jsp";
	}
}

ModelAndView

 

[Spring] Model, ModelMap, ModelAndView 차이점

Spring Model, ModelMap, ModelAndView 차이점 Model, ModelMap Vs ModelAndView 차이점 데이터만 저장한다 vs 데이터와 이동하고자 하는 View Page를 같이 저장한다 Model, ModelMap 공통점 model.addAttribute("..

javaoop.tistory.com

 

Controller로 return "jspName"; 이렇게 String을 반환하면 어떤 일이 벌어질까?

결론

ModelAndView 객체로 바꿔서 반환한다.

 

스프링MVC에서 return type이 String 일경우.

모 커뮤니티에 스프링 컨트롤러에서 ModelAndView가 아닌 String 으로 반환 할 경우 어떻게 되나 라는 글이 올라왔다. 대충 알고 있지만, 한정 정리를 해볼까한다. 소스코드 : STS케플러 버전에서 Spring

bistros.tistory.com

 

'Programming' 카테고리의 다른 글

Spring 04  (0) 2021.02.07
Spring 03  (0) 2021.02.07
Spring 01  (0) 2021.02.07
Java 05  (0) 2021.02.07
Java 04  (0) 2021.02.07
profile

Zero to Hero

@Doljae

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!