안녕하세요 토비님. 강의중 질문있습니다.
안녕하세요 강의 잘 듣고있는 학생입니다.
다름이 아니라 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를 구성하는 과정에서 이미 팩토리 메서드 정보를 사용한 것 같은데, 그렇다면 이미 빈을 만드는데 필요한 정보는 다 가지고 있는것이 아닌가? 라고 생각이 듭니다. 이런 부분들이 자꾸 맘에 걸려서 다음강의로 못넘어가겠습니다 ㅠㅠ 명확하게 정리해주시면 감사하겠습니다..
답변 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





