반응형
ApplicationContext가 스프링 컨테이너 이다.
public static void main(String[] args) {
GenericApplicationContext applicationContext = new GenericApplicationContext();
applicationContext.registerBean(HelloController.class);
applicationContext.refresh();
ServletWebServerFactory serverFactory = new TomcatServletWebServerFactory();
WebServer webServer = serverFactory.getWebServer(servletContext -> {
servletContext.addServlet("frontcontroller", new HttpServlet() {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 인증, 보안, 다국어, 공통 기능
if(req.getRequestURI().equals("/hello") && req.getMethod().equals(HttpMethod.GET.name())){
String name = req.getParameter("name");
HelloController bean = applicationContext.getBean(HelloController.class);
String ret = bean.hello(name);
resp.setContentType(MediaType.TEXT_PLAIN_VALUE);
resp.getWriter().println(ret);
}else{
resp.setStatus(HttpStatus.NOT_FOUND.value());
}
}
}).addMapping("/*"); // /밑으로 들어오는건 다 처리하겠다.
});
webServer.start();
}
Spring Container의 경우 object를 singleTon으로 유지되게끔 해준다.
DI
Spring Container( Assembler )
//interface
public interface HelloService {
String sayHello(String name);
}
//class
public class SimpleHelloService implements HelloService {
@Override
public String sayHello(String name){
return "Hello " + name;
}
}
//class
public class HelloController {
private final HelloService helloService;
public HelloController(HelloService helloService){
this.helloService = helloService;
}
public String hello(String name){
return helloService.sayHello(Objects.requireNonNull(name));
}
}
//main
public static void main(String[] args) {
GenericApplicationContext applicationContext = new GenericApplicationContext();
applicationContext.registerBean(HelloController.class);
applicationContext.registerBean(SimpleHelloService.class);
applicationContext.refresh();
ServletWebServerFactory serverFactory = new TomcatServletWebServerFactory();
WebServer webServer = serverFactory.getWebServer(servletContext -> {
servletContext.addServlet("frontcontroller", new HttpServlet() {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 인증, 보안, 다국어, 공통 기능
if(req.getRequestURI().equals("/hello") && req.getMethod().equals(HttpMethod.GET.name())){
String name = req.getParameter("name");
HelloController bean = applicationContext.getBean(HelloController.class);
String ret = bean.hello(name);
resp.setContentType(MediaType.TEXT_PLAIN_VALUE);
resp.getWriter().println(ret);
}else{
resp.setStatus(HttpStatus.NOT_FOUND.value());
}
}
}).addMapping("/*"); // /밑으로 들어오는건 다 처리하겠다.
});
webServer.start();
}
DispatcherServlet
RequestMapping -> GetMapping, PostMapping으로 간결하게 추가
@RestController가 붙은 Controller는 하위 메소드들에 모두 @ResponseBody 붙인다.
//class
@RequestMapping("/hello")
public class HelloController {
private final HelloService helloService;
public HelloController(HelloService helloService){
this.helloService = helloService;
}
@GetMapping
@ResponseBody
public String hello(String name){
return helloService.sayHello(Objects.requireNonNull(name));
}
}
//main
public static void main(String[] args) {
//스프링 컨테이너
GenericWebApplicationContext applicationContext = new GenericWebApplicationContext();
applicationContext.registerBean(HelloController.class);
applicationContext.registerBean(SimpleHelloService.class);
applicationContext.refresh();
//서블릿 컨테이너
ServletWebServerFactory serverFactory = new TomcatServletWebServerFactory();
WebServer webServer = serverFactory.getWebServer(servletContext -> {
servletContext.addServlet("dispatcherServlet",
new DispatcherServlet(applicationContext)
).addMapping("/*"); // /밑으로 들어오는건 다 처리하겠다.
});
webServer.start();
}
아래는
Bean을 등록하는 FactoryMethod 방식
@Configuration
public class HellobootApplication {
@Bean
public HelloController helloController(HelloService helloService){
return new HelloController(helloService);
}
@Bean
public HelloService helloService(){ //interface 타입으로 리턴하자
return new SimpleHelloService();
}
public static void main(String[] args) {
//스프링 컨테이너
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext(){
@Override
protected void onRefresh() {
super.onRefresh();
//서블릿 컨테이너
ServletWebServerFactory serverFactory = new TomcatServletWebServerFactory();
WebServer webServer = serverFactory.getWebServer(servletContext -> {
servletContext.addServlet("dispatcherServlet",
new DispatcherServlet(this)
).addMapping("/*"); // /밑으로 들어오는건 다 처리하겠다.
});
webServer.start();
}
};
applicationContext.register(HellobootApplication.class);
applicationContext.refresh(); //초기화
}
}
Factory 방식말고 더 간결하게 하는 방법
@ComponentScan으로 설정된 파일의 동일부터 하위까지의 @Component가 붙은 파일을 모두 Bean으로 등록한다.
메타 애노테이션이란 애노테이션 위에 애노테이션이 붙은
애노테이션을 만들려면
@Retention 이 필요 언제까지 살아있을것인가.
//Annotation
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Component
public @interface MyComponent {
}
//HelloController
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//스프링 컨테이너가 초기화 될때 실행된다.
System.out.println(applicationContext);
}
-> 스프링컨테이너에서 관리가 가능하면 생성자 주입도 가능하다. set메서드 삭제 후 생성자 주입변경
public HelloController(HelloService helloService, ApplicationContext applicationContext){
this.helloService = helloService;
this.applicationContext = applicationContext;
}
@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) {
//스프링 컨테이너
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext(){
@Override
protected void onRefresh() {
super.onRefresh();
//서블릿 컨테이너
ServletWebServerFactory serverFactory = this.getBean(ServletWebServerFactory.class);
DispatcherServlet dispatcherServlet = this.getBean(DispatcherServlet.class);
//set하지 않아도 dispatcherServlet에서 setApplication을 해준다.
dispatcherServlet.setApplicationContext(this);
WebServer webServer = serverFactory.getWebServer(servletContext -> {
servletContext.addServlet("dispatcherServlet",dispatcherServlet)
.addMapping("/*"); // /밑으로 들어오는건 다 처리하겠다.
});
webServer.start();
}
};
applicationContext.register(HellobootApplication.class);
applicationContext.refresh(); //초기화
}
}
최종적으로
//MySpringApplication
public class MySpringApplication {
public static void run(Class<?> applicationClass, String... args) {
//스프링 컨테이너
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext(){
@Override
protected void onRefresh() {
super.onRefresh();
//서블릿 컨테이너
ServletWebServerFactory serverFactory = this.getBean(ServletWebServerFactory.class);
DispatcherServlet dispatcherServlet = this.getBean(DispatcherServlet.class);
dispatcherServlet.setApplicationContext(this);
WebServer webServer = serverFactory.getWebServer(servletContext -> {
servletContext.addServlet("dispatcherServlet",dispatcherServlet)
.addMapping("/*"); // /밑으로 들어오는건 다 처리하겠다.
});
webServer.start();
}
};
applicationContext.register(applicationClass);
applicationContext.refresh(); //초기화
}
}
//HellobootApplication
@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) {
MySpringApplication.run(HellobootApplication.class, args);
}
}
반응형
'인강 > 토비의 스프링부트' 카테고리의 다른 글
스프링부트 자동구성 애플리케이션 (0) | 2023.02.06 |
---|---|
스프링부트 테스트 (0) | 2023.02.06 |
스프링부트 서블릿 (0) | 2023.02.04 |
스프링 부트 (0) | 2023.02.04 |