1. 리플렉션으로 단일 진입점 만들기

<aside> 💡

스프링 입장에서는 개발자가 어떤 메서드를 만들지 알 수 없고, 개발자가 메서드를 추가할 때 마다 스프링 코드를 수정해야 합니다. 그래서 동적으로 처리를 위해 리플렉션이 필요한 것입니다.

동적 분석을 할때 가장 쉬운 방법은 깃발(어노테이션)을 사용하는 것

</aside>

image.png

image.png

package ex04.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RequestMapping {
    String value(); // 어노테이션의 속성값 (value만 사용시 키값 생략 가능)
}

package ex04.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface RestController {
}

package ex04;

import ex04.anno.RequestMapping;
import ex04.anno.RestController;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class DispatcherServlet {
    // IoC 컨테이너 = 제어의 역전
    public List<Object> iocContainer = new ArrayList<>();

    // 1.컴퍼넌트 스캔해서 ioc 컨테이너에 객체 추가
    public void componentScan(String folder) throws Exception {
        // 1. 패키지스캔
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        URL packageUrl = classLoader.getResource(folder);
        File ex04Folder = new File(packageUrl.toURI());
        File[] files = ex04Folder.listFiles(); // anno, App, BoardController, UserController

        // 2. 찾은 것들을 new해서 컬렉션에 담아두기
        for (File f : files){
            //System.out.println(f.getName());
            if(f.getName().endsWith(".class")){
                String className = folder+"."+f.getName().replace(".class", ""); // ex04.BoardController, ex04.UserController
                // ex04.BoardController, ex04.UserController, ex04.App
                Class cls = Class.forName(className); // JVM 문자열로 클래스 로딩
                //System.out.println(cls);

                if(cls.isAnnotationPresent(RestController.class)){
                    System.out.println(cls);
                    Object instance = cls.newInstance();
                    iocContainer.add(instance);
                }
            }
        }
    }

    // 2.컴퍼넌트 스캔 대상에서 메서드 찾기
    public void findUri(String value){
        for(Object instance : iocContainer){
            Method[] methods = instance.getClass().getDeclaredMethods();
            for (Method method : methods) {
                RequestMapping rm = method.getDeclaredAnnotation(RequestMapping.class);
                if(rm.value().equals(value)){
                    try {
                        method.invoke(instance);
                        break;
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            }
        }
    }

}

package ex04;

import ex04.anno.RequestMapping;
import ex04.anno.RestController;

@RestController
public class BoardController {

    @RequestMapping("/select")
    public String select(){
        System.out.println("select 호출됨");
        return "apple";
    }

    @RequestMapping("/insert")
    public void insert(){
        System.out.println("insert 호출됨");
    }

    @RequestMapping(value = "/delete")
    public void delete(){
        System.out.println("delete 호출됨");
    }

    @RequestMapping(value = "/update")
    public void update(){
        System.out.println("update 호출됨");
    }

}

package ex04;

import ex04.anno.RequestMapping;
import ex04.anno.RestController;

@RestController
public class UserController {

    @RequestMapping("/login")
    public void login(){
        System.out.println("login 호출됨");
    }
}

package ex04;

public class App {

    public static void main(String[] args) throws Exception {
        // 1. 키보드 입력자리
        String uri = "/reply/write";

        // 2. 컴퍼넌트 스캔
        DispatcherServlet ds = new DispatcherServlet();
        ds.componentScan("ex04");

        // 3. 메서드 호출
        ds.findUri(uri);
    }
}

2. 스프링으로 컨트롤러 만들어보기

컨트롤러는 외부 클라이언트(브라우저)의 요청을 처음으로 받는 곳!!

<aside> 💡

프레임워크 = 틀+일하다

스프링 = 봄이 왔다!!

신입 좋고, 관리자 좋고!!

</aside>

image.png

package com.example.v4;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class BoardController {

    @GetMapping("/insert")
    public String insert() {
        System.out.println("insert 호출됨");
        return "apple";
    }

    @GetMapping("/delete")
    public void delete() {
        System.out.println("delete 호출됨");
    }

    @GetMapping("/update")
    public void update() {
        System.out.println("update 호출됨");
    }
}