Springboot jar是如何启动的

Springboot jar是如何启动的

可执行的jar 启动

使用java jar 命令生成jar包,会自动生成 META-INF/MANIFEST.MF

spring-boot3-graavm-image>jar cvfe aaa.jar pr.iceworld.fernando.springboot3.image.MainApplication ./target/classes

会生成

Manifest-Version: 1.0
Created-By: 17.0.5 (BellSoft)
Main-Class: pr.iceworld.fernando.springboot3.image.MainApplication

指定了Main-Classpr.iceworld.fernando.springboot3.image.MainApplication

Springboot 工程jar是如何启动的

会生成一个${工程名}-${工程版本}.jar
里面包含jar所需要的META-INF/MANIFEST.MF

Manifest-Version: 1.0
Created-By: Maven JAR Plugin 3.3.0
Build-Jdk-Spec: 17
Implementation-Title: spring-boot3-graavm-image
Implementation-Version: 3.0.0
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: pr.iceworld.fernando.springboot3.image.MainApplication
Spring-Boot-Version: 3.0.0
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Spring-Boot-Layers-Index: BOOT-INF/layers.idx

spring-boot-maven-plugin 会帮我们指定
Main-Classorg.springframework.boot.loader.JarLauncher
Start-Classpr.iceworld.fernando.springboot3.image.MainApplication

JarLauncher 就是 springboot jar 的启动入口类

public class JarLauncher extends ExecutableArchiveLauncher {
	// ...
	public static void main(String[] args) throws Exception {
		// 最终调用 Launcher#launcher(String[])
		new JarLauncher().launch(args);
	}
}	

ExecutableArchiveLauncher 的父类是 Launcher

public abstract class ExecutableArchiveLauncher extends Launcher {
	// ...
	private static final String START_CLASS_ATTRIBUTE = "Start-Class";
	// ...
	@Override
	protected String getMainClass() throws Exception {
		Manifest manifest = this.archive.getManifest();
		String mainClass = null;
		if (manifest != null) {
			mainClass = manifest.getMainAttributes().getValue(START_CLASS_ATTRIBUTE);
		}
		if (mainClass == null) {
			throw new IllegalStateException("No 'Start-Class' manifest entry specified in " + this);
		}
		return mainClass;
	}
	// ...
}
public abstract class Launcher {
	// ...
	protected void launch(String[] args) throws Exception {
		if (!isExploded()) {
			// 注册能解析spring boot jar 的Handler
			JarFile.registerUrlProtocolHandler();
		}
		// 创建 Springboot 自定义 ClassLoader
		ClassLoader classLoader = createClassLoader(getClassPathArchivesIterator());
		String jarMode = System.getProperty("jarmode");
		// 默认使用 getMainClass() 获取 `META-INF/MANIFEST.MF`Start-Class` 值
		String launchClass = (jarMode != null && !jarMode.isEmpty()) ? JAR_MODE_LAUNCHER : getMainClass();
		// 反射调用应用程序主类 `Start-Class`值
		launch(args, launchClass, classLoader);
	}
	// ...
	protected void launch(String[] args, String launchClass, ClassLoader classLoader) throws Exception {
		Thread.currentThread().setContextClassLoader(classLoader);
		createMainMethodRunner(launchClass, args, classLoader).run();
	}
	// ...
	protected MainMethodRunner createMainMethodRunner(String mainClass, String[] args, ClassLoader classLoader) {
		return new MainMethodRunner(mainClass, args);
	}
	// ...
	protected boolean isExploded() {
		return false;
	}
	// ...
}
public class MainMethodRunner {

	private final String mainClassName;

	private final String[] args;

	public MainMethodRunner(String mainClass, String[] args) {
		this.mainClassName = mainClass;
		this.args = (args != null) ? args.clone() : null;
	}

	// 通过反射调用 `Start-Class`
	public void run() throws Exception {
		Class<?> mainClass = Class.forName(this.mainClassName, false, Thread.currentThread().getContextClassLoader());
		Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);
		mainMethod.setAccessible(true);
		mainMethod.invoke(null, new Object[] { this.args });
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值