inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

토비의 스프링 부트 - 이해와 원리

자바코드 구성 정보 사용

안녕하세요 토비님. 강의중 질문있습니다.

해결된 질문

493

김경현

작성한 질문수 4

0

안녕하세요 강의 잘 듣고있는 학생입니다.

다름이 아니라 applicationContext의 생성과정이 아직 스스로 정리가 되어있지 않아 이렇게 질문을 드립니다..

우선 제 생각은 이렇습니다.

applicationContext를 생성하면서 내부적으로 onRefresh() 를 오버라이딩을 합니다.

여기서

ServletWebServerFactory serverFactory = this.getBean(ServletWebServerFactory.class);
DispatcherServlet dispatcherServlet = this.getBean(DispatcherServlet.class);

을 통해서 등록된 Bean을 들고오게 됩니다.

여기서 드는 의문점1은, this.getBean(DispatcherServlet.class)을 한다는 것은 이미 DispatcherServlet이 Bean등록이 되어있다는 것이고 그렇다면 applicationContext라는 변수를 만들기 전에 이미 Bean이 등록이 되어있었다고 생각됩니다.

그러면 applicationContext라는 변수를 방금 막 선언하고 아직 객체를 할당하는 과정인데 this.getBean이 작동한다?

this는 분명 applicationContext인데 어떻게 applicationContext안의 getBean을 통해 dispatcherServlet등이 불러와지는지 모르겠습니다.. (요약하면, 아직 인스턴스를 만들지 않았는데 어떻게 applicationContext안의 getBean이 동작할 수 있는가? 입니다)

 

두번째는, 어떻게든 위의 과정을 거쳐서 applicationContext(스프링 컨테이너)가 서블릿 컨테이너와 연결이 되었습니다. 이후 applicationContext.register(HellobootApplication.class)를 하게되는데, 이미 위에서 빈 등록도 다 하고 모든걸 가지고 있는것 같은데 왜 register가 필요한것인지 모르겠습니다 ㅠㅠ

register하는 코드는

HellobootApplication.class라는 클래스 구성정보를 읽어서 그 내용을 토대로 빈(이때 이 빈은 HellobootApplication 빈 일까요??)을 등록한다 라고 생각되는데, HellobootApplication 클래스의 정보에는 팩토리 메서드 2개(ServletWebServerFactory,DispatcherServlet) 와

applicationContext를 구성하는 코드밖에 없다고 생각됩니다. applicationContext를 구성하는 과정에서 이미 팩토리 메서드 정보를 사용한 것 같은데, 그렇다면 이미 빈을 만드는데 필요한 정보는 다 가지고 있는것이 아닌가? 라고 생각이 듭니다. 이런 부분들이 자꾸 맘에 걸려서 다음강의로 못넘어가겠습니다 ㅠㅠ 명확하게 정리해주시면 감사하겠습니다..

spring spring-boot spring-jdbc

답변 3

0

토비

익명 클래스를 이용해서 onRefresh를 오버라이드한 부분을 말씀하시는 것이군요.

여기서 onRefresh()는 new AnnotationConfigWebApplicationContext()로 오브젝트가 만들어질 때 실행되는 게 아닙니다. 여기서 만들어지는 오브젝트의 한 메소드일 뿐이죠. 이게 실행되는 시점은 가장 아래 refresh()를 호출해서 applicationContext의 내부 빈을 초기화 한 다음이죠. 그때 위에 정의한 onRefresh()의 코드가 실행됩니다.

익명클래스처럼 메소드 내부에서 클래스가 재정의되는 경우에는, 코드가 나열되 순서와 실행 순서가 일치하지 않습니다.

 

0

김경현

답변 감사합니다.

그렇다면 맨 밑줄 바로위의 register는 어떤행동을 하는걸까요?

이미 HelloApplication 내부의 팩토리 메서드를 통해 빈 등록도 했고, 스프링컨테이너와 서블릿컨테이너도 연결했는데, 무엇을 위한것인지 잘 모르겠습니다.

구체적으로 어떤일을 하는지 궁금합니다.

0

토비

register()가 HelloApplication 클래스를 빈으로 등록해주는 역할을 하는 거죠.

main() 메소드가 실행됐다고 HelloApplication 클래스가 빈으로 저절로 등록되는 게 아닙니다. 따라서 @Bean 팩토리 메소드도 빈이 되지 않죠. 그게 정의된 클래스를 스프링의 빈으로 쓰겠다고 applicationContext에 등록해줘야 합니다.
main()은 static 메소드죠. 이건 HelloApplication 클래스 안에 넣어놨을 뿐 전혀 상관없는 코드입니다. main()이 실행된다고 HelloApplication 클래스가 알아서 스프링 애플리케이션 컨텍스트에 등록되지 않습니다.
그래서 register()를 호출해서 직접 등록해줘야 합니다.

0

김경현

아..!

그럼 실제 main()이 실행되고 register이후 refresh가 되면서 팩토리 메서드 정보로 빈을 생성하고 서블릿컨테이너와도 연결을 하게 되면서 applicationContext 빈이 생성되는것이군요.

늦은 시간에 답변해주셔서 감사합니다!

0

토비

강의 어느 단계의 코드인지를 잘 모르겠어서 답변을 드리기가 쉽지 않네요. 워낙 많은 단계가 있어서요.

말씀하시는 내용이 담긴 메소드 코드 전체를 옮겨주시면 설명드리겠습니다.

0

김경현

Bean의 생명주기 메소드 << 이 부분입니다!

package tobyspring.helloboot;

import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServer;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;



@Configuration
@ComponentScan
public class HellobootApplication {

       @Bean
       public ServletWebServerFactory servletWebServerFactory(){
          return new TomcatServletWebServerFactory();
       }
       @Bean
    
       public DispatcherServlet dispatcherServlet(){
          return new DispatcherServlet();
       }
    public static void main(String[] args) {
       System.out.println(ServletWebServerFactory.class);

       AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext(){

          @Override
          protected void onRefresh() {
             super.onRefresh();
             ServletWebServerFactory serverFactory = this.getBean(ServletWebServerFactory.class);
             DispatcherServlet dispatcherServlet = this.getBean(DispatcherServlet.class);

           

             WebServer webServer = serverFactory.getWebServer(servletContext -> {
                servletContext.addServlet("dispatcherServlet",dispatcherServlet
                      ).addMapping("/*");
             });

             webServer.start();
          }
       };

       applicationContext.register(HellobootApplication.class);
       
       applicationContext.refresh();



    }


}

 

0

김경현

아.. 뭔가 제가 this를 잘못 알고있는 것 같네요..

this 가 new AnnotationConfigWebApplicationContext
오브젝트라면, 이 오브젝트가 beanFactory를 참조해서 현재 등록된 빈 정보를 통해 getBean()을 하고 이렇게 얻어진 서블렛 컨테이너를 스프링 컨테이너에 연결을 한다.

라고 다시 생각되는군요..
그렇다면 applicationContext.register(HellobootApplication.class); 는 어떻게 해석하는게 옳을까요?
applicationContext는 이미 서블렛 컨테이너와 연결된 것을 알고 있을텐데, 이걸 등록해야하는 이유는 뭘까요? ㅠㅠ 자꾸 의문이 의문을 낳는군요

11강에서 cmd에서 spring shell에 $ init 하면 Fail 메세지

0

75

2

TestRestTemplate 을 통해 테스트 실행시 웹 요청 정보가 콘솔에 표시되지 않습니다.

0

85

1

섹션7. 자동구성 정보파일분리 강의 질문(@MyAutoConfiguration 붙힌 이유)

0

202

2

WebApplicationContext를 DispatcherServlet에 this로 넘기는 것

0

279

2

인프라 빈 구성 정보의 분리에서 EnableMyAutoConfiguration 질문드립니다.

0

210

2

질문드립니다.

0

233

2

spring boot 3.3.7로 학습중입니다.

0

371

2

Serverproperties 객체 생성 후 @Impor 어노테이션 사용 이유 용도

0

162

2

spring start io 에서 이제더이상 2.x버전은 지원하지 않는 것 같습니다.

1

298

2

Springboot 3.2 이상에서 파라미터 추론관련

0

918

4

binding error

0

222

3

Arrays.copyOf 메서드의 타입 세이프

1

156

2

MyOnClassCondition에 있는 matches method의 Invoke 횟수

1

233

3

인용구의 출처가 궁금합니다.

0

259

1

프로퍼티 빈의 후처리기 도입 AnnotationUtils의 사용

0

236

2

SimpleCacheConfiguration과 빈 등록

0

169

2

MyAutoConfigImportSelector 에서 생성자로 ClassLoader를 주입받을 수 있는 점

0

244

1

IntelliJ project jenerator spring initailizr

0

150

1

강의 자료 레퍼지토리에 업로드

0

216

1

강의자료

0

388

1

Hikari 라이브러리가 없으면 오류가 나는거 아닌가요

0

314

2

Tomcat 포트 프로퍼티 미설정시 랜덤 포트 설정 문의

0

476

5

@Import 로 Bean을 등록해야하는 기준이 뭔지 궁금합니다.

0

343

2

application.properties파일내 프로퍼티 이름

0

214

1