ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • spring MVC - requestScope 빈 주입
    Spring/Spring MVC 2021. 12. 27. 23:03
    반응형

    빈 주입

    • @Autowired를 활용하여 Bean을 주입받을 수 있다
    • 스프링 코어에서 Prototype과 Singleton이 있었다.
    • Spring MVC에서는 추가로 Request, Session, Application을 제공한다.

    requestScope 빈 주입

    • Bean을 정의할 때 Request Scope로 정의하면 요청이 발생할 때마다 bean 객체가 생성되어 자동으로 주입
    • 주입된 Bean은 요청 발생 시 주입만 이루어지는 것이므로 request 영역에 저장되지는 않는다.
    • xml로 Bean을 설정하고 Byname으로 주입받았을 경우에만 request 영역에 자동 저장된다.

     


    방법 1 - Java, RequestScope bean 주입

    1.  Bytype 으로 주입
    2.  Byname 으로 주입
    3.  Component 으로 주입

    기본적으로 주입 되는 bean 객체들은

    Sring data1, String data2 클래스 변수, setter getter만 넣었다.

     

     

    RootAppContext.java에서 정의한 bean 주입

     @Configuration을 이용하여 Bean 등록하는 클래스(RootAppContext.java를 만들어 준 후 bean 등록을 해준다.

     

    // 프로젝트 작업시 사용할 bean을 정의하는 클래스
    @Configuration
    public class RootAppContext {
    
    	@Bean
    	@RequestScope
    	public DataBean1 dataBean1() {
    		return new DataBean1();
    	}
    	
    	@Bean("requestBean2")
    	@RequestScope
    	public DataBean2 dataBean2() {
    		return new DataBean2();
    	}
    }

    @Bean에 이름을 안 정해주면 Bytype으로 클래스 이름으로 등록되고,

    @Bean에 이름을 정해주면 Byname으로 등록한 것과 같다.

    @Configuration
     - 해당 클래스가 Bean을 정의하는 클래스라고 Annotation을 통해 알려준다.

    @Bean                       
     - Bytype : 클래스 이름이 name이 된다.

    @Bean("requestBean2") 
     - Byname : requestBean2 가 이름이 된다.

    @RequestScope
     - 이 Bean이 주입되는 시점을 나타내는 스코프, 새로운 요청(URL)이 발생했을 때 이 메서드가 호출된다.

     

     이제 Controller에서 주입받아 사용해보자.

    @Controller
    public class testController {
    	
    	@Autowired
    	DataBean1 requestBean1;
    	
    	@Resource(name = "requestBean2")
    	DataBean2 requestBean2;
    
    	@GetMapping("/test1")
    	public String test1() {
    		requestBean1.setData1("문자열1");
    		requestBean1.setData2("문자열2");
    		
    		requestBean2.setData3("문자열3");
    		requestBean2.setData4("문자열4");
    		
    		return "forward:/result1";
    	}
    	
    	@GetMapping("/result1")
    	public String result1(Model model) {
    		
    		System.out.println("requestBean.data1 : " + requestBean1.getData1());
    		System.out.println("requestBean.data2 : " + requestBean1.getData2());
    
    		System.out.println("requestBean.data3 : " + requestBean2.getData3());
    		System.out.println("requestBean.data4 : " + requestBean2.getData4());
    	
    		model.addAttribute("requestBean1", requestBean1);
    		model.addAttribute("requestBean2", requestBean2);
    
    		
    		return "result1";
    	}
    }

     여기서 주의할 점은 DataBean1과 DataBean2이 Controller에 주입이 된 것이지 request 영역에

    저장된게 아니다. 따라서 jsp에 데이터를 넘겨주고 싶으면 Request Scope에 저장해야 한다.

    (여기에서는 Model 객체를 사용하였다.)

    @Autowired
     - Bytype으로 해당 Bean을 주입받는다

    @Resource(name = "requestBean2")
     - Byname으로 해당 Bean을 주입받는 방식, xml과 다르게 자동으로 reqeust 영역에 저장이 안 된다. 주의!

     

    @Component으로 정의한 bean 주입
    //Bytype으로 등록
    @Component
    //Byname으로 등록
    //@Component(value = "requestBean4")
    @RequestScope
    public class DataBean3 {
    	
    	private String data5;
    	private String data6;
    	
    	// ... getter setter 
    }

     우선 @Component로 bean을 등록해준다. 그다음은 @Component를 scan할 수 있도록

    ServletAppContext.java에 @ComponentScan("kr.co.softcampus.beans")을 넣어 스캔할 패키지를 추가한다.

    @Configuration
    @EnableWebMvc
    // 스캔할 패키지를 지정한다.
    @ComponentScan("kr.co.controller")
    @ComponentScan("kr.co.beans")
    public class ServletAppContext implements WebMvcConfigurer{
    	@Override
    	public void configureViewResolvers(ViewResolverRegistry registry) {
    		.....
    	}
    	
    	@Override
    	public void addResourceHandlers(ResourceHandlerRegistry registry) {
    		.....
    	}
    }
    @ComponentScan("kr.co.beans")
     - Bean을 정의한 Component 클래스를 찾을 수 있도록 Scan 해 준다.

     

    이제 Controller에서 사용하면 된다.

    @Controller
    public class testController {
    
    	@Autowired
    	DataBean3 requestBean3;
    	
    	@Resource(name = "requestBean4")
    	DataBean4 requestBean4;
    	
    	@GetMapping("/test1")
    	public String test1() {
    		
    		requestBean3.setData5("문자열5");
    		requestBean3.setData6("문자열6");
    		
    		requestBean4.setData7("문자열7");
    		requestBean4.setData8("문자열8");
    		
    		return "forward:/result1";
    	}
    	
    	@GetMapping("/result1")
    	public String result1(Model model) {
    
    		System.out.println("requestBean.data5 : " + requestBean3.getData5());
    		System.out.println("requestBean.data6 : " + requestBean3.getData6());
    		
    		System.out.println("requestBean.data7 : " + requestBean4.getData7());
    		System.out.println("requestBean.data8 : " + requestBean4.getData8());
    
    		model.addAttribute("requestBean3", requestBean3);
    		model.addAttribute("requestBean4", requestBean4);
    		
    		return "result1";
    	}
    }

     여기서도 Bytype, Byname으로 2가지 방법으로 주입받아서 사용하였다. 마찬가지로 JSP에서 사용하기 위해서는

    Controller에서 주입받은 Bean들을 Request 영역에 저장해 주어야한다.

     


     

    방법 2 - xml, RequestScope bean 주입

     우선 DataBean1 클래스와 DataBean2 클래스를 만들어주고 시작한다.

     

     

    root-context.xml 에 등록한 bean 주입
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	   xsi:schemaLocation="http://www.springframework.org/schema/beans
    	   					   http://www.springframework.org/schema/beans/spring-beans.xsd">
    	   <bean class='kr.co.beans.DataBean1' scope='request'/>   
    	   <bean id = 'requestBean2' class='kr.co.beans.DataBean2' scope='request'/>
    </beans>
    <bean class='kr.co.beans.DataBean1' scope='request'/>
     - id값 정해주지 않았기 때문에 클래스 명인 dataBean1 이름으로 세팅된다. (Bytype 방식) 

    <bean id = 'requestBean2' class='kr.co.beans.DataBean2' scope='request'/>
     - id값을 정해줬기 때문에 id값인 requestbean2 이름으로 세팅된다. (Byname 방식)

    scope='request'
     - 이 Bean이 주입되는 시점을 나타내는 스코프, 새로운 요청(URL)이 발생했을 때 이 메서드가 호출된다.

     

    @Controller
    public class testController {
    	
    	@Autowired
    	@Lazy
    	DataBean1 requestBean1;
    	
    	@Resource(name = "requestBean2")
    	@Lazy
    	DataBean2 requestBean2;
    	
    	@GetMapping("/test1")
    	public String test1() {
    		requestBean1.setData1("문자열1");
    		requestBean1.setData2("문자열2");
    		
    		requestBean2.setData3("문자열3");
    		requestBean2.setData4("문자열4");
    
    		return "forward:/result1";
    	}
    	
    	@GetMapping("/result1")
    	public String result1(Model model) {
    		
    		System.out.println("requestBean.data1 : " + requestBean1.getData1());
    		System.out.println("requestBean.data2 : " + requestBean1.getData2());
    		
    		System.out.println("requestBean.data3 : " + requestBean2.getData3());
    		System.out.println("requestBean.data4 : " + requestBean2.getData4());
    
    		model.addAttribute("requestBean1", requestBean1);
    		
    		return "result1";
    	}
    }

     여기서 방법 1과 차이점이 있다. xml은 Byname으로 주입하게 되면 자동으로 request 영역에 저장해준다.

    따라서 Byname으로 주입받은 bean은 request 영역에 따로 저장할 필요가 없다.

    @Autowired
     - Bytype으로 해당 Bean을 주입받는다.

    @Lazy
     - 요청이 발생하지도 않았는데 bean을 주입하려고 해서 오류가 발생하기 때문에 @Lazy 어노테이션을 넣어준다.

    @Resource(name = "requestBean2")
     - Byname으로 해당 Bean을 주입받는다.
     - Byname으로 주입받은 Bean은 Request 영역에 자동으로 저장된다.

     


     

    @Component에 등록한 bean 주입

     등록할 DataBean3, DataBean4는 위 방법 1 코드와 동일하므로 생략하겠다.

     

     우선 @Component을 스캔할 수 있도록 servlet-context.xml에 

    <context:component-scan base-package="kr.co.softcampus.beans"/>를 넣어준다.

    <?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/mvc"
    			 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    			 xmlns:beans="http://www.springframework.org/schema/beans"
    			 xmlns:context="http://www.springframework.org/schema/context"
    			 xsi:schemaLocation="http://www.springframework.org/schema/mvc
    			 		     http://www.springframework.org/schema/mvc/spring-mvc.xsd
    			 		     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">
    
    	<annotation-driven/>
        
    	<!-- 스캔할 bean들이 모여있는 패키지를 지정한다. -->
    	<context:component-scan base-package="kr.co.controller"/>
    	<context:component-scan base-package="kr.co.beans"/>
    
    	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    		<beans:property name="prefix" value="/WEB-INF/views/"/>
    		<beans:property name="suffix" value=".jsp"/>
    	</beans:bean>
    	
    	<resources mapping="/**" location="/resources/"/>
    	
    			 
    </beans:beans>
    <context:component-scan base-package="kr.co.beans"/>
     - Bean을 정의한 Component 클래스를 찾을 수 있도록 Scan 해 준다.

     

     이제 Controller에서 사용하면 된다.

    @Controller
    public class testController {
    
    	@Autowired
    	@Lazy
    	DataBean3 requestBean3;
    	
    	@Resource(name = "requestBean4")
    	@Lazy
    	DataBean4 requestBean4;
    	
    	@GetMapping("/test1")
    	public String test1() {
    
    		requestBean3.setData5("문자열5");
    		requestBean3.setData6("문자열6");
    		
    		requestBean4.setData7("문자열7");
    		requestBean4.setData8("문자열8");
    
    		return "forward:/result1";
    	}
    	
    	@GetMapping("/result1")
    	public String result1(Model model) {
    
    	
    		System.out.println("requestBean.data5 : " + requestBean3.getData5());
    		System.out.println("requestBean.data6 : " + requestBean3.getData6());
    		
    		System.out.println("requestBean.data7 : " + requestBean4.getData7());
    		System.out.println("requestBean.data8 : " + requestBean4.getData8());
    
    		model.addAttribute("requestBean3", requestBean3);
    		model.addAttribute("requestBean4", requestBean4);
    		
    		
    		return "result1";
    	}
    }

     여기서 주의할 점은 @Component로 등록된 Bean은 Byname으로 주입하여도 request영역에 저장이 안 된다.

    따라서 jsp에서 데이터를 사용하고 싶으면 request에 직접 저장해 줘야 한다.

    @Resource(name = "requestBean4") 
     - @Component로 등록되어 주입된 Bean은 request 영역에 저장되지 않는다. 
    반응형

    댓글

Designed by Tistory.