spring - boot - run 명령 은 Spring Boot 프로젝트 를 어떻게 실행 합 니까?

저자: 사호 왕https://segmentfault.com/a/1190000021687878
초학 봄 Boot 할 때 공식 문서 에 따라 프로젝트 를 만 든 다음 에 실 행 됩 니 다.  mvn spring-boot:run  이 프로젝트 를 실행 할 수 있 습 니 다.
나 는 이 명령 이 도대체 무엇 을 했 는 지, 그리고 왜 프로젝트 에 main 방법 이 포함 되 어 있 는 그 class 가 하 나 를 더 해 야 하 는 지 궁금 했다. @SpringBootApplication  의 주 해 는?
이 주 해 를 왜 넣 었 는 지 @ SpringBootApplication 이후 mvn spring-boot:run 명령 을 내리 면 이 클 라 스 를 찾 아 main 방법 을 실행 할 수 있 습 니까?
우선, Maven 으로 새로 만 든 spring boot 프로젝트, pom. xml 에 이러한 설정 이 있 음 을 알 게 되 었 습 니 다.
  
      
          
            org.springframework.boot  
            spring-boot-maven-plugin  
          
      
      

보아하니 mvn spring-boot:run 명령 은 이 플러그 인 이 제공 한 것 일 것 입 니 다.
Maven 플러그 인의 개발 메커니즘 을 몰라 서 잘 모 르 겠 어 요. 그래서 찾 아 봤 어 요. maven 의 플러그 인 개발 문서:
http://maven.apache.org/guides/plugin/guide-java-plugin-development.html
공식 문서 에 따 르 면 Maven 플러그 인 은 여러 가지 목표 가 있 습 니 다. 모든 목 표 는 Mojo 류 입 니 다. 예 를 들 어  mvn spring-boot:run  이 명령, spring - boot 이 부분 은 maven 플러그 인 입 니 다. run 이 부분 은 maven 의 목표 또는 명령 입 니 다.
maven 플러그 인 개발 문서 에 따라  spring-boot-maven-plugin  프로젝트 의 RunMojo. java, 바로 mvn spring-boot:run 이 명령 이 실행 중인 자바 코드 입 니 다.
관건 적 인 방법 은 두 가지 가 있 는데, 하 나 는?  runWithForkedJvm, 하 나 는 runWithMavenJvm 입 니 다. pom. xml 이 상기 설정 과 같 으 면 실 행 됩 니 다.  runWithForkedJvm pom. xml 의 설정 이 다음 과 같 으 면 실행 runWithMavenJvm:
  
      
          
            org.springframework.boot  
            spring-boot-maven-plugin  
              
                false  
              
          
      
      
runWithForkedJvm  ... 과  runWithMavenJvm  전 자 는 현재 프로젝트 를 실행 하 는 프로 세 스 를 시작 하고 후 자 는 현재 프로젝트 를 실행 하 는 스 레 드 를 시작 하 는 것 입 니 다.
제 가 먼저 알 고 있 는 건 요.  runWithForkedJvm
private int forkJvm(File workingDirectory, List args, Map environmentVariables)    
      throws MojoExecutionException {    
   try {    
      RunProcess runProcess = new RunProcess(workingDirectory, new JavaExecutable().toString());    
  Runtime.getRuntime().addShutdownHook(new Thread(new RunProcessKiller(runProcess)));    
  return runProcess.run(true, args, environmentVariables);    
  }    
   catch (Exception ex) {    
      throw new MojoExecutionException("Could not exec java", ex);    
  }    
}  

이 코드 에 따 르 면 RunProcess 는 spring - boot - loader - tools 프로젝트 에서 제공 합 니 다. 제공 해 야 할 working Directory 는 프로젝트 컴 파일 된 * class 파일 이 있 는 디 렉 터 리 입 니 다. environment Variables 는 분 석 된 환경 변수 입 니 다. args 에 서 는 spring - boot 의 sample 프로젝트 에 대해 주로 main 방법 이 있 는 클래스 입 니 다.인 용 된 라 이브 러 리 의 경로 입 니 다.
working Directory 는 maven 의 ${procject} 변 수 를 빠르게 얻 을 수 있 기 때문에 여기 서 관건 은 main 방법 이 있 는 클래스 를 어떻게 찾 았 는 지, 그리고 인 용 된 라 이브 러 리 의 경 로 를 어떻게 얻 었 는 지 입 니 다.
main 방법 을 찾 는 클래스 의 실현 은  AbstractRunMojo.java  안쪽:
mainClass = MainClassFinder.findSingleMainClass(this.classesDirectory, SPRING\_BOOT\_APPLICATION\_CLASS\_NAME);  
MainClassFinder.java  spring - boot - loader - tools 에서 제공 하 는 것 입 니 다. main 방법 을 찾 는 종 류 는 주로 다음 과 같은 코드 입 니 다.
static  T doWithMainClasses(File rootFolder, MainClassCallback callback) throws IOException {  
    if (!rootFolder.exists()) {  
        return null; // nothing to do  
    }  
    if (!rootFolder.isDirectory()) {  
        throw new IllegalArgumentException("Invalid root folder '" + rootFolder + "'");  
    }  
    String prefix = rootFolder.getAbsolutePath() + "/";  
    Deque stack = new ArrayDeque<>();  
    stack.push(rootFolder);  
    while (!stack.isEmpty()) {  
        File file = stack.pop();  
        if (file.isFile()) {  
            try (InputStream inputStream = new FileInputStream(file)) {  
                ClassDescriptor classDescriptor = createClassDescriptor(inputStream);  
                if (classDescriptor != null && classDescriptor.isMainMethodFound()) {  
                    String className = convertToClassName(file.getAbsolutePath(), prefix);  
                    T result = callback.doWith(new MainClass(className, classDescriptor.getAnnotationNames()));  
                    if (result != null) {  
                        return result;  
                    }  
                }  
            }  
        }  
        if (file.isDirectory()) {  
            pushAllSorted(stack, file.listFiles(PACKAGE_FOLDER_FILTER));  
            pushAllSorted(stack, file.listFiles(CLASS_FILE_FILTER));  
        }  
    }  
    return null;  
}  

여기 서 핵심 은 spring 의 asm 프레임 워 크 를 이용 하여 class 파일 의 바이트 코드 를 읽 고 분석 하여 main 방법 이 포 함 된 클래스 를 찾 은 다음 에 이 클래스 가 사용 되 었 는 지 판단 하 는 것 입 니 다. @SpringBootApplication 주석, 있 으 면 실행 할 코드 파일 에 속 합 니 다.
프로젝트 에 main 방법 이 여러 개 있 고 @ SpringBootApplication 에 의 해 주해 류 라면 코드 는 찾 은 첫 번 째 실행 을 직접 선택 하 는 것 같 습 니 다.
의존 하 는 라 이브 러 리 경 로 를 읽 습 니 다. spring - boot - maven - plugin 에 대량의 코드 가 있 습 니까? 아니면 Maven 자체 의 특성 을 이용 하여 이 루어 집 니까?
알 수 있 는 이 정보 에 따라 저 는 일반적인 자바 프로젝트 bootexp 를 새로 만 들 었 습 니 다. 간단 한 코드 로 spring boot 프로젝트 를 실행 합 니 다.
package com.shahuwang.bootexp;  

import java.io.File;  
import java.io.IOException;  
import java.util.ArrayList;  
import java.util.HashMap;  
import java.util.List;  
import java.util.Map;  

import org.springframework.boot.loader.tools.JavaExecutable;  
import org.springframework.boot.loader.tools.MainClassFinder;  
import org.springframework.boot.loader.tools.RunProcess;  

public class Runner  
{  
    public static void main( String[] args ) throws IOException {  
        String SPRING_BOOT_APPLICATION_CLASS_NAME = "org.springframework.boot.autoconfigure.SpringBootApplication";  
        File classesDirectory = new File("C:\\share\\bootsample\\target\\classes");  
        String mainClass = MainClassFinder.findSingleMainClass(classesDirectory, SPRING_BOOT_APPLICATION_CLASS_NAME);  
        RunProcess runProcess = new RunProcess(classesDirectory, new JavaExecutable().toString());  
        Runtime.getRuntime().addShutdownHook(new Thread(new RunProcessKiller(runProcess)));  
        List params = new ArrayList<>();  
        params.add("-cp");  
        params.add("     ")  
        params.add(mainClass);  
        Map environmentVariables = new HashMap<>();  
        runProcess.run(true, params, environmentVariables);  
    }  

    private static final class RunProcessKiller implements Runnable {  

        private final RunProcess runProcess;  

        private RunProcessKiller(RunProcess runProcess) {  
            this.runProcess = runProcess;  
        }  

        @Override  
        public void run() {  
            this.runProcess.kill();  
        }  

    }  
}  

관련 라 이브 러 리 의 경 로 를 가 져 옵 니 다. 모두 spring - boot - maven - plugin 프로젝트 의 개인 적 인 방법 입 니 다. 그래서 저 는 bootsample 이라는 spring boot 프로젝트 에서 직접 실행 합 니 다.  mvn spring-boot:run -X classpath 를 출력 하고 classpath 를 복사 하면 됩 니 다.bootexp 프로젝트 를 실행 하면 bootsample 이라는 spring boot 프로젝트 를 실행 할 수 있 습 니 다.
그래서 왜 spring boot 의 프로젝트, main 방법 이 있 는 클래스 에 주 해 를 붙 여야 하 는 지, @ SpringBootApplication 이라는 의문 도 해결 되 었 습 니 다.
종합 하여 mvn spring-boot:run 이 명령 은 왜 하나의 spring boot 프로젝트 를 실행 할 수 있 는 지 그다지 신 비 롭 지 않 습 니 다. 여기 서 주요 한 난점 은 두 가지 입 니 다. 하 나 는 Maven 플러그 인의 개발 입 니 다. 프로젝트 의 설정 정 보 를 얻 고 명령 을 수행 합 니 다.하 나 는 클래스 로드 메커니즘 과 주해 분석 이다.
위 챗 공식 번호 주목: 자바 기술 창고, 배경 에서 답장: boot, 내 가 정리 한 N 편의 Spring Boot 를 얻 을 수 있 습 니 다. 튜 토리 얼 은 모두 건어물 이다.
제 블 로그 에 가서 더 많이 읽 는 것 을 추천 합 니 다.
1. 자바 JVM, 집합, 다 중 스 레 드, 새로운 기능 시리즈 튜 토리 얼
2. Spring MVC, Spring Boot, Spring Cloud 시리즈 튜 토리 얼
3. Maven, Git, Eclipse, Intellij IDEA 시리즈 도구 튜 토리 얼
4. 자바, 백 엔 드, 구조, 알 리 바 바 등 대형 공장 의 최신 면접 문제
좋 은 것 같 아 요. 좋아요 + 리 트 윗 하 는 거 잊 지 마 세 요!

좋은 웹페이지 즐겨찾기