Недавно у меня есть время, чтобы оптимизировать открытую платформу API компании. Когда я печатал пакет JAR, я вдруг понял, что раньше использовал Spring Boot, но я никогда не знал начального принципа банки, созданной Spring Boot. Затем на этот раз я расстегнула банку и посмотрел на нее. Это действительно отличалось от того, что я представлял. Ниже приведен полный анализ расслабленной банки.
Приложение Spring Boot не опубликовано. Структура более простой демонстрации похожа. Кроме того, версия Spring Boot, которую я использовал, составляет 1.4.1. В Интернете есть еще одна статья, чтобы проанализировать стартап Spring Boot Jar. Это должно быть ниже 1.4, а метод запуска также сильно отличается от текущей версии.
После MVN Clean Install, когда мы посмотрим в целевой каталог, мы найдем два пакета JAR, следующим образом:
xxxx.jarxxx.jar.original
Это объясняется механизмом подключаемого модуля Spring Boot, который превращает обычную банку в исполняемый пакет JAR, а xxx.jar.original-это пакет JAR, созданный Maven. Их можно найти в связи со статьей на официальном весеннем веб -сайте, следующим образом:
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#executable-jar
Ниже приводится часть структуры каталога JAR, созданной приложением Spring Boot, большинство из которых опущены, и отображаются только важные части.
.├ack-inf│ ├ack-class│ ├ack. Применение-дев. │ │ │ │ │ │ │ │ │ │ │ │ │ │ └ └ │ │ │ │ │ │ │ │ └ └ └ │ │ │ │ │ │ │ └ └ └ │ │ │ │ │ │ │ │ │ └ └ └ │ │ │ │ │ │ │ │ │ │ └ └ └ └ │ │ │ │ │ │ │ └ │ │ │ │ │ └ └ └ │ │ │ │ │ │ │ │ │ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ └ │ └ └ └ └ │ │ └ └ └ └ └ │ │ │ │ │ │ └ │ │ │ │ │ └ └ ½ swaggerConfig.class│ │ │ │ ├ ├ack of oauth2│ │ │ │ ├ ├ │ │ ├ ├ ─ ├ │ │ │ ├ ├ Контроллер │ │ │ ├ ├ ½ guru.css│ │ ├ack ├ │ │ ├ ├ack1200x628.png│ │ └ └ ├ ├бя newbannerboots_2.png│ └---í ├ ├ ├ └ └ └ └ newbannerboots_2.png│ └ack ─ ├ ├ ├ ├ ├ ├ ├ └ └ └ └ ├ ├ ├ ├ ├- └acke Open-server-openapi│ ├acke ├ack. ├ack wanlvenureRlclassloader.class ├acker -установку. EpplodedArchive $ fileEntryiterator $ entrycomparator.class ├ack in explodedarchive $ fileEntryiterator.class
В дополнение к классу, который мы написали в приложении, эта JAR также имеет отдельный пакет ORG. Должно быть, приложение Spring Boot использует плагин Spring Boot для ввода этого пакета, который предназначен для улучшения этапа пакета в жизненном цикле MVN. Именно этот пакет играет ключевую роль в процессе запуска. Кроме того, в JAR вводится различные зависимости, требуемые приложением, и введен дополнительный пакет Spring Boot. Эта банка, которая может All-in-One, также называется Fat.jar. Здесь мы всегда будем использовать fat.jar, чтобы заменить название банки.
В настоящее время мы продолжим смотреть на файл Manifest.mf в Meta-Inf, следующим образом:
Manifest-Version: 1.0implementation Title: Open :: Server :: OpenApiimplementation-версия: 1,0-Snapshotarchiver-версия: Plexus archiverbuilt-by: xiaxuanimplementation-vendor-id: weibangong.openspring-boot-version: 1.4.1.reeleaseptonation-vendor-vendor-vendor-vendor vendor vendor vendor vendor vendor vendor vendor vendor vendor vendor wendor org.springframework.boot.loader.propertieslauncherstart-class: com.weibangong.open.openapi.springbootwebapplicationspring-boot-class: boot-inf/spring-boot-lib: boot-inf/lib/create-by: apache maven 3.9build-jdk: 1,8.0_20-letmentation- http://maven.apache.org/open-server-openapi
В основном класс, указанный здесь, представляет собой файл класса в пакете, который введен отдельно вместо нашей программы запуска, а затем файл Manifest.mf имеет отдельный класс Start, который указывает программу запуска нашего приложения.
Сначала мы находим класс org.springframework.boot.loader.propertieslauncher, где основной метод:
public static void main (string [] args) выбрасывает исключение {PropertiesLauncher Launcher = new PropertiesLauncher (); args = launcher.getargs (args); Launcher.launch (args);}Проверьте метод запуска. Этот метод найден в пусковой установке родительского класса, а метод запуска родительского класса выглядит следующим образом:
Запуск Protected void (string [] args, string mainclass, classloader classloader) throws exection {thread.currentThread (). SetContextClassLoader (classLoader); this.createmainmethodrunner (Mainclass, Args, ClassLoader) .run (); } защищенный MainMethodrunner CreateMainMethodrunner (String mainclass, String [] args, classloader classloader) {return new Mainmethodrunner (Mainclass, Args); }Метод запуска, наконец, вызывает метод Createmainmethodrunner, который создает инстанции объекта Mainmethodrunner и запускает метод запуска. Мы перейдем к исходному коду Mainmethodrunner следующим образом:
пакет org.springframework.boot.loader; import java.lang.reflect.method; открытый класс Mainmethodrunner {private final String mainclassname; частная финальная строка [] args; public mainmethodrunner (String mainclass, string [] args) {this.mainclassname = mainclass; this.args = args == null? null: (String []) args.clone (); } public void run () throws exception {class mainclass = thread.currentthread (). getContextClassloader (). Метод mainmethod = mainclass.getDeclaredMethod ("main", new Class [] {String []. Class}); mainmethod.invoke ((объект) null, новый объект [] {this.args}); }}Проверяя метод запуска, очень легко запустить пружинный багажник, и анализ в основном закончился.
5. Запуск процесса основной программы
После разговора о начальном процессе JAR, давайте поговорим о процессе запуска и загрузки основной программы в приложении Spring Boot. Во -первых, давайте посмотрим на основной метод приложения Spring Boot.
Пакет cn.com.devh; import org.springframework.boot.springapplication; импорт org.springframework.boot.autoconfigure.springbootapplication; импорт org.springframework.cloud.client.discovery.ansablediscyclient; импорт; org.springframework.cloud.netflix.eureka.enableeurekaclient; импорт org.springframework.cloud.netflix.feign.enablefeignclients;/*** Создан Xiaxuan 17/8/25. */@SpringbootApplication@enableFeignClients@enableteurekaclientpublic class a1serviceaplication {public static void main (string [] args) {SpringApplication.run (a1serviceApplicamation.class, args); }}Перейдите к методу запуска в Springapplication, следующим образом:
/** * Статический помощник, который можно использовать для запуска {@link Spressapplication} из указанного источника с использованием настройки по умолчанию. * @param Источник Источник для загрузки * @param Args Аргументы приложения (обычно передается из основного метода Java) * @return running {@link ApplicationContext} */ public Static ConfigurableApplicationContext run (источник объекта, строка ... args) {return run (новый объект [] {source}, args); } /** * Статический помощник, который можно использовать для запуска {@link SpringApplication} из указанных источников, используя настройки по умолчанию и аргументы, предоставленные пользователем. * @param Источники Источники для загрузки * @param Args Аргументы приложения (обычно передаваемые из основного метода Java) * @return the Running {@link ApplicationContext} */ Public Static ConfigurableApplicationContext Run (Object [] источники, string [] args) {return New Spresspplication (источники) .Run (args); }Здесь создание экземпляра Springapplication является ключом, мы перейдем к конструктору Springapplication.
/*** Создать новый экземпляр {@link SpringApplication}. Контекст приложения будет загружать * бобы из указанных источников (см. {@Link SpressApplication Class-уровни} * документация для деталей. Экземпляру можно настроить перед вызовом * {@link #run (String ...)}. * @Param Sources Источники Beans * @see #run (объект, строка []) * @se #springpplication (resourceload, object objectarciation (object, string []). {инициализируйте (источники); ApplicationContextInitializer.class);DevuceWebenVironment () в методе инициализации здесь определяет, начинается ли он в настоящее время с веб -приложения или обычной банки, следующим образом:
Private Boolean DeduceWebenVironment () {for (String classname: web_environment_classes) {if (! classutils.ispresent (classname, null)) {return false; }} вернуть true; }Web_environment_classes:
Частная статическая конечная строка [] web_environment_classes = {"javax.servlet.servlet", "org.springframework.web.context.configerailityWebApplicationContext"};Пока любого из них не существует, текущее применение запускается в форме обычной банки.
Затем метод SetInitializers инициализирует все приложения ContextInitializers,
/** * Устанавливает {@Link ApplicationContextInitialize}, который будет применен к пружине * {@Link ApplicationContext}. * @param инициализаторы инициализаторы для установки */ public void setinitializers (collection <? Extends ApplicationContextInitializer <? >> инициализаторы) {this.initializers = new ArrayList <ApplicationContextInitializer <? >> (); this.initializers.addall (инициализаторы); } setListeners ((collection) getSpringfactoryoriesInstances (ApplicationListener.class)) **Этот шаг инициализирует всех слушателей.
Давайте вернемся к предыдущему Springapplication (источники) .RUN (ARGS); и введите метод запуска, код выглядит следующим образом:
/** * Запустите приложение Spring, создавая и обновляя новый * {@link ApplicationContext}. * @param Args Аргументы приложения (обычно передаются из основного метода Java) * @return a Running {@link ApplicationContext} */ public ConfigurableApplicationContext Run (String ... args) {spectwatch spectwatch = new Spectwatch (); Spectwatch.start (); ConfiguruRableApplicationContext context = null; ConfigureHeadlessProperty (); SpringApplicationRunlisteners Slirlers = GetRunListeners (ARGS); Слушатели.started (); try {ApplicationArguments ApplicationArguments = new DefaultApplicationArguments (args); context = createAndrefreshcontext (слушатели, ApplicationArguments); AfterRefresh (контекст, ApplicationArguments); слушатели. Spectwatch.stop (); if (this.logstartupinfo) {new Startupinfologger (this.mainapplicationclass) .logstarted (getApplicationlog (), spectwatch); } вернуть контекст; } catch (Throwable ex) {handlerUnfailure (контекст, слушатели, Ex); бросить новое нелегальное статей (Ex); }}Этот шаг выполняет создание контекста
Private ConfigurableApplicationContext createAndrefreshcontext (SpringApplicationRunlisteners Слушатели, ApplicationArguments ApplicationArguments) {configuruRableApplicationContext контекст; // Создание и настройка среды настраиваемой среды среды = getorcreateenvironment (); ConfigureEnvironment (Environment, ApplicationArguments.getSourceargs ()); Слушатели. EnvironmentPrepared (окружающая среда); if (iswebenvironment (Environment) &&! this.webenvironment) {EnvironmentTostOstandArdEndVironment (Environment); } if (this.bannermode! = banner.mode.off) {printbanner (среда); } // Создать, загружать, обновить и запустить контекст ApplicationContext = createApplicationContext (); Context.SetEnvironment (среда); PostProcessApplicationContext (контекст); применятьинализатор (контекст); Слушатели. ContextPrepared (контекст); if (this.logstartupinfo) {logstartupinfo (context.getParent () == null); logstartupprofileinfo (контекст); } // Добавить специфические для загрузки context.getbeanfactory (). Registersingleton ("SpringApplicationArguments", ApplicationArguments); // Загрузите источники набор <object> источники = getSources (); Assert.notempty (источники, «источники не должны быть пустыми»); нагрузка (контекст, источники. Слушатели. Contextload (контекст); // освежить контекст обновления (контекст); if (this.registerShutDownHook) {try {context.registerShutDownHook (); } catch (accessControlexception ex) {// не допускается в некоторых средах. }} вернуть контекст; } // Создание и настройка среды, настраивающуюся среду, среда, среда, = getorCreateEnvironment (); ConfigureEnvironment (Environment, ApplicationArguments.getSourceargs ());Этот шаг выполняет конфигурацию и загрузку среды.
if (this.bannermode! = banner.mode.off) {printbanner (среда); }Этот шаг печатает логотип Spring Boot. Если вам нужно изменить его, добавьте Banner.txt и Banner.txt в файл ресурса, чтобы изменить его на нужный вам шаблон.
// Создать, загружать, обновить и запустить контекст ApplicationContext = CreateApplicationContext (); return (configurableApplicationContext) beanutils.instantiate (contextclass)
Контекст создания действительно включает в себя то, что создается контейнер, и экстремирует класс ответов, включая создание EmbeddedServletContainerFactory, независимо от того, выбрать ли причал или Tomcat, есть много контента, поэтому я расскажу об этом в следующий раз.
if (this.registerShutDownHook) {try {context.registerShutDownHook (); } catch (accessControlexception ex) {// не допускается в некоторых средах. }}Этот шаг состоит в том, чтобы зарегистрировать текущий контекст и уничтожить контейнер при получении команды убийства.
По сути, начальный анализ закончился, но есть все еще некоторые детали, которые очень много трудоемки. Это будет обсуждаться в последующем посте в блоге, и это все на сегодня.
Таким образом, процесс запуска пружинного багажника в основном представляет собой следующие шаги:
1. Когда мы обычно упаковываем Maven, плагин Spring Boot расширяет жизненный цикл Maven и вдаляет пакет, связанный с пружинной загрузкой в банку. Эта JAR содержит файлы классов, связанные с программой запуска Spring Boot, помимо банок, созданных приложением.
2. Я видел процесс запуска немного более низкой версии Spring Boot Jar. В то время я помню, что текущий поток имеет новый поток для запуска основной программы, и теперь она была изменена, чтобы напрямую использовать отражение для запуска основной программы.
Суммировать
Выше приведено анализ принципа пружинного багажа, введенного вам редактором. Я надеюсь, что это будет полезно для вас. Если у вас есть какие -либо вопросы, пожалуйста, оставьте мне сообщение, и редактор ответит вам вовремя. Большое спасибо за вашу поддержку сайту wulin.com!