Kata pengantar
Artikel ini menganalisis prinsip kerja Spring Boot 1.3. Spring Boot 1.4. Setelah itu, struktur pengemasan ditemukan berubah dan direktori boot-INF ditambahkan, tetapi prinsip dasarnya tetap tidak berubah.
Untuk perubahan ClassLoader di Spring Boot 1.4.*, Silakan merujuk ke: http://www.vevb.com/article/141479.htm
Mulai dengan cepat boot musim semi
Di Spring Boot, fitur yang sangat menarik adalah bahwa aplikasi dapat dikemas langsung ke dalam toples/perang, dan kemudian toples/perang ini dapat dimulai secara langsung tanpa mengkonfigurasi server web lain.
Jika Anda belum pernah menggunakan Spring Boot sebelumnya, Anda dapat mengalaminya melalui demo di bawah ini.
Berikut adalah proyek sebagai contoh untuk menunjukkan cara memulai proyek boot musim semi:
git clone [email protected]: hengyunabc/spring-boot-demo.gitmvn spring-boot-demojava -jar target/demo-0.0.1-snapshot.jar
Jika IDE yang digunakan adalah pegas atau ide, Anda dapat membuat proyek boot pegas melalui wizard.
Anda juga dapat merujuk ke tutorial resmi:
http://docs.spring.io/spring-boot/docs/current-snapshot/reference/htmlsingle/#getting-started-first-application
Dua pertanyaan tentang boot musim semi
Saat pertama kali Anda mulai menghubungi Spring Boot, Anda biasanya memiliki pertanyaan ini
Mari kita analisis bagaimana boot musim semi dilakukan.
Bagaimana Spring Boot dimulai saat dikemas sebagai toples tunggal
Setelah Maven dikemas, dua file jar akan dihasilkan:
demo-0.0.1-snapshot.jardemo-0.0.1-snapshot.jar.original
di mana demo-0.0.1-snapshot.jar.original adalah paket yang dihasilkan maven-jar-plugin default.
Demo-0.0.1-snapshot.jar adalah paket JAR yang dihasilkan oleh plug-in Spring Boot Maven, yang berisi dependensi aplikasi dan kelas terkait boot pegas. Selanjutnya, ini disebut toples gemuk.
Pertama, mari kita periksa struktur direktori paket yang disiapkan oleh Spring Boot (hilangkan jika tidak penting):
├── Meta-Inf│ ├── Manifest.mf├─ Appligent.properties├── Com│ └── Misge│ └── SpringbootdemoApplication.class ├── lib│ ├─ ─ ─ ├ ├ ├ ├ ├ ├ ├ ├ ├ ├ ├ ├ ├ ├ ├ ├ ├ belas ├ ├ ilangan or ├ ilangan or ├ ilangan buah └── Loader ├── ExecutIvearchivelauncher.class ├── Jarlauncher.Class ├── JavaAgentDetector.Class ├── luncurkan MainMethodRunnerer.class ├ - launcher. Kelas ├── MainMethodrunner.Class ├─ Mis ... - .......................
Mari kita lihat konten ini secara bergantian.
Manifest.mf
Manifest-Versi: 1.0Start-Class: com.example.springbootDemoapplicationImplementation-vendor-id: com.examplespring-boot-versi: 1.3.0.releasecreated-by: Apache Maven 3.3.3Build-JDK: 1.8.0_60Implemation-vVEN-VVEND-PERVEN-PINDK: PENVOL-VIRET: 1.8.0_60Implemation-vVEN-VVEND-PERVEN-PENDING: PV: 1.8.0_60Implemation-vVEN-VVENDALE-PENDURANG-PERNAD-PERNADP: 1.8.0_60IMPLEMEPASI-PLOCASE-VVEN-PERVEN: org.springframework.boot.loader.jarlauncher
Anda dapat melihat bahwa kelas utama adalah org.springframework.boot.loader.jarlauncher, yang merupakan fungsi utama yang dimulai oleh JAR.
Ada juga kelas awal yang com.example.springbootdemoApplication, yang merupakan fungsi utama yang kami terapkan.
@SpringbootApplicationPublic kelas springbootDemoApplication {public static void main (string [] args) {springApplication.run (springbootdemoapplication.class, args); }} COM/Contoh direktori
Berikut adalah file .class aplikasi.
direktori lib
Berikut adalah file paket JAR yang bergantung pada aplikasi.
Misalnya, Spring-Beans, Spring-MVC dan stoples lainnya.
Direktori org/springframework/boot/loader
Berikut adalah file .class dari Spring Boot Loader.
Konsep Arsip
Di Spring Boot, konsep arsip disarikan.
Arsip dapat berupa toples (Jarfilearchive) atau direktori file (ExplodedArchive). Ini dapat dipahami sebagai lapisan sumber daya akses terpadu yang diabstraksikan oleh Spring Boot.
Demo-0.0.1-snapshot.jar di atas adalah arsip, dan kemudian setiap paket JAR di bawah direktori /lib di demo-0.0.1-snapshot.jar juga merupakan arsip.
Publik Abstrak Kelas Arsip {URL abstrak publik getUrl (); string publik getMainClass (); Koleksi Abstrak Publik <TREST> GETEnTries (); Daftar Abstrak Publik <CRIVE> GetNestedArchives (EntryFilter Filter);Anda dapat melihat bahwa arsip memiliki URL sendiri, seperti:
jar: file: /tmp/target/demo-0.0.1-snapshot.jar!/
Ada juga fungsi GetNestedArchives, yang sebenarnya mengembalikan daftar arsip di bawah Demo-0.0.1-Snapshot.jar/Lib. URL mereka adalah:
JAR: File: /tmp/target/demo-0.0.1-snapshot.jar! /lib/aopalliance-1.0.jarjar: file: /tmp/target/demo-0.0.1-snapshot.jar! /lib/spring-beans-4.2.3.jelas
Jarlauncher
Dari manifest.mf, kita dapat melihat bahwa fungsi utamanya adalah Jarlauncher. Mari kita analisis alur kerjanya di bawah ini.
Struktur warisan kelas Jarlauncher adalah:
Kelas Jarlauncher memperluas ExecutIvearchivelAlauncherClass ExecutivearchivelAnuncher memperluas peluncur
Buat arsip dengan demo-0.0.1-snapshot.jar:
Jarlauncher pertama-tama menemukan jalur toples tempat ia berada, yaitu, demo-0.0.1-snapshot.jar, dan kemudian menciptakan arsip.
Kode berikut menunjukkan trik cara menemukan lokasi pemuatan dari kelas:
Createarchive arsip akhir yang dilindungi () melempar Exception {protectionDomain protectionDomain = getClass (). getProtectionDomain (); Codesource codesource = protectionDomain.getCodesource (); URI Location = (codesource == null? Null: codesource.getLocation (). Pouri ()); String path = (location == null? Null: location.getschemespecificPart ()); if (path == null) {lempar baru ilegalstateException ("Tidak dapat menentukan arsip sumber kode"); } File root = file baru (path); if (! root.exists ()) {lempar baru ilegalstateException ("tidak dapat menentukan arsip sumber kode dari" + root); } return (root.isdirectory ()? new ExplodedArchive (root): New Jarfilearchive (root));} Dapatkan stoples di bawah lib/ dan buat luncur luncur
Setelah Jarlauncher membuat arsip, ia menggunakan fungsi GetNestedArchives untuk mendapatkan semua file JAR di bawah demo-0.0.1-snapshot.jar/lib dan membuatnya sebagai daftar.
Perhatikan bahwa seperti yang disebutkan di atas, Archive memiliki URL sendiri.
Setelah mendapatkan URL arsip ini, Anda akan mendapatkan array URL [], dan menggunakannya untuk membangun classloader kustom: LaunchedUrlClassLoader.
Setelah membuat classloader, baca kelas mulai dari manifest.mf, yaitu, com.example.springbootDemoApplication, dan kemudian membuat utas baru untuk memulai fungsi utama aplikasi.
/*** Luncurkan aplikasi yang diberikan file arsip dan classloader yang dikonfigurasi penuh. */Protected Void Launch (String [] args, String MainClass, ClassLoader ClassLoader) melempar Exception {runnable runner = createMainMethodrunner (MainClass, args, ClassLoader); Thread runnerthread = utas baru (runner); runnerThread.setContextClassLoader (ClassLoader); runnerthread.setname (thread.currentThread (). getName ()); runnerThread.start ();}/*** Buat {@code mainMethodrunner} yang digunakan untuk meluncurkan aplikasi. */Protected Runnable CreateMainMethodRunner (String MainClass, String [] args, ClassLoader ClassLoader) melempar Exception {class <?> runnerClass = classLoader.LoadClass (runner_class); Konstruktor <?> constructor = runnerclass.getConstructor (string.class, string []. Class); return (runnable) constructor.newinstance (MainClass, args);} LaunchedUrlClassLoader
Perbedaan antara LaunchUrlClassLoader dan UrlClassloader biasa adalah bahwa ia memberikan kemampuan untuk memuat .class dari arsip.
Menggabungkan fungsi getentries yang disediakan oleh Archive, Anda bisa mendapatkan sumber daya di arsip. Tentu saja masih ada banyak detail di dalamnya, jadi saya akan menjelaskannya di bawah ini.
Ringkasan Proses Startup Aplikasi Spring Boot
Setelah melihat ini, Anda dapat meringkas proses startup aplikasi boot musim semi:
Detail di Spring Boot Loader
Alamat kode: https://github.com/spring-projects/spring-boot/tree/master/spring-boot-tools/spring-boot-loader
Perpanjangan URL Jarfile
Spring Boot dapat dimulai dengan toples gemuk. Yang paling penting adalah mengimplementasikan metode pemuatan toples dalam toples.
Definisi URL Jarfile asli JDK dapat ditemukan di sini:
http://docs.oracle.com/javase/7/docs/api/java/net/jarurlconnection.html
URL Jarfile asli terlihat seperti ini:
jar: file: /tmp/target/demo-0.0.1-snapshot.jar!/
URL Sumber Daya dalam Paket JAR:
Salin kode sebagai berikut: jar: file: /tmp/target/demo-0.0.1-snapshot.jar! /Com/example/springbootdemoapplication.class
Anda dapat melihat bahwa untuk sumber daya dalam toples, definisi dipisahkan oleh '!/'. URL Jarfile asli hanya mendukung satu '!/'.
Spring Boot memperluas protokol ini untuk mendukung beberapa '!/', Yang dapat mewakili Jar dalam Jar, Jar di Directory Resources.
Misalnya, URL berikut mewakili Spring-Beans-4.2.3.release.jar di Direktori LIB Demo-0.0.1-Snapshot.jar:
Salin kode sebagai berikut: jar: file: /tmp/target/demo-0.0.1-snapshot.jar! /Lib/spring-beans-4.2.3.release.jar! /Meta-inf/manifest.mf
UrlStreamHandler khusus, Perpanjang Jarfile dan Jarurlconnection
Saat membangun URL, Anda dapat melewati pawang, dan JDK dilengkapi dengan kelas pawang default. Aplikasi dapat mendaftarkan pawang itu sendiri untuk menangani URL khusus.
URL publik (protokol string, host string, port int, file string, handler urlstreamhandler) melempar Malformedurlexception
Lihat:
https://docs.oracle.com/javase/8/docs/api/java/net/url.html#url-java.lang.string-java.lang.string-int-java.lang.string-
Spring Boot menangani logika ganda dalam toples dengan mendaftarkan kelas penangan khusus.
Pawang ini akan menggunakan softreference untuk cache semua jarfile terbuka.
Saat memproses URL seperti berikut, pemisah '!/' Diproses bersepeda. Mulai dari lapisan atas, pertama-tama buatlah Jarfile Demo-0.0.1-Snapshot.jar, kemudian membangun Jarfile Spring-Beans-4.2.3.release.jar, dan kemudian membangun koneksi jaring yang menunjuk ke manifest.mf.
Salin kode sebagai berikut: jar: file: /tmp/target/demo-0.0.1-snapshot.jar! /Lib/spring-beans-4.2.3.release.jar! /Meta-inf/manifest.mf
//org.springframework.boot.loader.jar.handlerpublic class handler memperluas UrlStreamHandler {private static final string pemisah = "!/"; private static softreference <peta <file, jarfile >> rootfileCache; @Override terlindungi URLConnection OpenConnection (URL URL) melempar ioException {if (this.jarfile! = Null) {return New JarUrlConnection (url, this.jarfile); } coba {return baru JarurlConnection (url, getrootjarfilefromurl (url)); } catch (Exception ex) {return OpenFallBackConnection (url, ex); }} public Jarfile getrootjarfilefromurl (url url) melempar ioException {string spec = url.getFile (); int pemisahindex = spec.indexof (pemisah); if (pemisahindex == -1) {lempar new Malformedurlexception ("Jar URL tidak mengandung!/ Pemisah"); } String name = spec.subString (0, separatorIndex); return getrootjarfile (name); } Bagaimana ClassLoader Membaca ke Sumber Daya
Kemampuan apa yang dibutuhkan untuk classloader?
API yang sesuai adalah:
URL publik FindResource (nama string) InputStream publik getResourCeAsstream (nama string)
Seperti yang disebutkan di atas, ketika konstruksi boot musim semi diluncurkan dengan classloader, ia melewati array URL []. Array adalah url toples di bawah direktori lib.
Bagaimana JDK atau ClassLoader tahu cara membaca konten di dalamnya untuk URL?
Faktanya, prosesnya terlihat seperti ini:
Panggilan terakhir adalah fungsi getInputStream () dari JarurlConnection.
//org.springframework.boot.loader.jar.jarurlconnection @Override inputStream publik getInputStream () melempar ioException {connect (); if (this.jarentryname.isempty ()) {lempar ioException baru ("Tidak ada nama entri yang ditentukan"); } return this.jarentrydata.getInputStream (); }Dari URL hingga akhirnya membaca konten di URL, seluruh prosesnya cukup rumit. Mari kita ringkas:
Ada banyak detail di sini, hanya beberapa poin penting yang terdaftar.
Lalu, bagaimana UrlClassloader GetResource?
Saat membangun URLClassLoader, ia memiliki parameter array URL [], dan akan menggunakan array ini untuk membangun URLClassPath:
Urlclasspath ucp = URLClassPath baru (URLS);
Di urlclasspath, loader akan dibangun untuk semua URL, dan kemudian ketika mendapatkan sumber daya, itu akan mencoba untuk mendapatkannya dari loader ini satu per satu.
Jika akuisisi berhasil, itu dikemas sebagai sumber daya seperti di bawah ini.
Sumber daya getResource (nama string akhir, cek boolean) {url url akhir; coba {url = url baru (base, parseutil.encodepath (name, false)); } catch (Malformedurlexception e) {lempar baru ilegalargumentException ("name"); } UrlConnection final UC; coba {if (centang) {urlclasspath.check (url); } uc = url.openconnection (); InputStream in = uc.getInputStream (); if (uc instanceof JarurlConnection) { / * perlu mengingat file jar sehingga dapat ditutup * dengan tergesa -gesa. */ JarurlConnection JUC = (JarurlConnection) UC; jarfile = jar mloader.checkjar (juc.getjarfile ()); }} catch (Exception e) {return null; } return new baru () {public string getName () {return name; } URL publik getUrl () {return url; } URL publik getCodesourceUrl () {return base; } public inputStream getInputStream () melempar ioException {return uc.getInputStream (); } public int getContentLength () melempar ioException {return uc.getContentLength (); }};}Seperti yang dapat Anda lihat dari kode, url.openconnection () sebenarnya dipanggil. Dengan cara ini rantai lengkap dapat dihubungkan.
Perhatikan bahwa kode kelas UrlClassPath tidak datang dengan sendirinya di JDK. Di sini Anda dapat melihat http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/sun/misc/urlclasspath.java#506
Mulai Aplikasi Spring Boot di Direktori IDE/OPEN
Di atas hanya disebutkan proses memulai aplikasi boot musim semi dalam toples lemak. Berikut ini adalah analisis tentang bagaimana Spring Boot dimulai di IDE.
Di IDE, fungsi utama yang langsung dijalankan adalah menerapkan fungsi utamanya sendiri:
@SpringbootApplicationPublic kelas springbootDemoApplication {public static void main (string [] args) {springApplication.run (springbootdemoapplication.class, args); }}Bahkan, mulai aplikasi boot musim semi di IDE adalah kasus termudah, karena stoples ketergantungan dimasukkan ke dalam classpath, jadi boot musim semi baru saja dimulai.
Situasi lain adalah memulai boot musim semi di direktori terbuka. Direktori terbuka yang disebut adalah mendekompresi toples lemak dan kemudian langsung memulai aplikasi.
java org.springframework.boot.loader.jarlauncher
Saat ini, Spring Boot akan menentukan apakah saat ini ada di direktori. Jika demikian, konstruk Explodedarkive (yang sebelumnya adalah Jarfilearchive), dan proses startup berikutnya mirip dengan toples lemak.
Emal Proses Startup Tomcat
Tentukan apakah itu di lingkungan web
Ketika Spring Boot dimulai, pertama -tama tentukan apakah itu ada di lingkungan web dengan hanya mencari kelas servlet:
Private Static Final String [] web_environment_classses = {"javax.servlet.servlet", "org.springframework.web.context.configableableWappleCicedContext"}; private boolean deduceWeNvironMent () {for for (string classname: web_eneneNean) {for string: web_enene_enenveMent () {for (string classname: web_enene_enene_enenveMent () {for classname: web_enene_enenveMent () {for className: Web_enenEnveMent (for string: web_eneneName: Web_eneneName: web_eneneNEMAMMENTE (for string (! Classutils.ispresent (className, null)) {return false; }} return true;}Jika demikian, AnnotationConfigemBedDedWebApplicationContext akan dibuat, jika tidak konteks musim semi adalah AnnotationConfigApplicationContext:
//org.springframework.boot.springapplication Dilindungi ConfigurableApplicationContext CreateApplicationContext () {class <?> contextclass = this.applicationContextClass; if (contextclass == null) {coba {contextclass = class.forname (this.webenvironment? Default_web_context_class: default_context_class); } catch (ClassNotFoundException ex) {Throw new IllegalStateException ("Tidak dapat membuat aplikasi default Default," + "Harap tentukan ApplicationContextClass", ex); }} return (configurableApplicationContext) beanutils.instantiate (ContextClass); } Dapatkan kelas implementasi dari embeddedServerContainererFactory
Spring Boot memulai server web yang sesuai dengan mendapatkan embeddedServerContainerFactory.
Dua kelas implementasi yang umum digunakan adalah tomcatembeddedservletcontainerfactory dan jettyembeddedservletcontainerFactory.
Kode untuk memulai Tomcat:
// tomcatembedservletcontainerfactory@overridepublic embeddedservletcontainer getembeddedservletcontainer (servletcontextInitializer ... inisialisasi) {tomcat tomcat = tomcat baru (); File berbasis = (this.basedirectory! = Null? This.basedir: createTempDir ("tomcat")); tomcat.setbasedir (basis.getAbsolutePath ()); Konektor konektor = konektor baru (this.protocol); tomcat.getService (). AddConnector (Connector); CustomizeConnector (Connector); tomcat.setConnector (konektor); tomcat.gethost (). setautodeploy (false); tomcat.getEngine (). SetbackgroundProcessordelay (-1); untuk (Connector TambahanConnector: this.additionalToMcatConnectors) {tomcat.getService (). AddConnector (tambahanconnector); } prepareContext (tomcat.gethost (), inisialisasi); kembalikan gettomcatembeddedservletcontainer (tomcat);} Direktori file sementara akan dibuat untuk Tomcat, seperti:
/tmp/tomcat.2233614112516545210.8080, sebagai basis Tomcat. File Tomcat sementara, seperti direktori kerja, akan ditempatkan di dalam.
Beberapa servlet tomcat juga akan diinisialisasi, seperti servlet default/JSP yang lebih penting:
private void addDefaultSerVlet (konteks konteks) {wrapper defaultservlet = context.createWrapper (); defaultServlet.setName ("default"); defaultServer.setservletclass ("org.apache.catalina.servlets.defaultservlet"); defaultServlet.addinitparameter ("debug", "0"); defaultServlet.addinitparameter ("daftar", "false"); DefaultSerVlet.SetLoadAnstartup (1); // jika tidak, lokasi default dari Spring DispatcherServlet tidak dapat ditetapkan defaultServlet.setOverridable (true); context.addChild (defaultServlet); context.addservletmapping ("/", "default");} private void addJspservlet (konteks konteks) {wrapper jspservlet = context.createWrapper (); jspservlet.setname ("jsp"); jspservlet.setservletclass (getjspservletclassname ()); jspservlet.addinitparameter ("fork", "false"); jspservlet.setloadonstartup (3); Context.addChild (jspservlet); context.addservletmapping ("*. jsp", "jsp"); context.addservletmapping ("*. jspx", "jsp");} Cara Mengakses Sumber Daya Dengan Aplikasi Web Spring Boot
Bagaimana cara mengakses sumber daya web saat aplikasi boot musim semi dikemas sebagai toples lemak?
Ini sebenarnya diimplementasikan melalui URL yang disediakan oleh Archive dan kemudian melalui kemampuan untuk mengakses sumber daya ClassPath yang disediakan oleh ClassLoader.
index.html
Misalnya, Anda perlu mengonfigurasi index.html, yang dapat ditempatkan langsung di direktori SRC/Main/Resources/statis dalam kode.
Untuk halaman selamat datang index.html, saat boot musim semi diinisialisasi, ViewController akan dibuat untuk ditangani:
// ResourceProPertiesPublic Class ResourceProperties mengimplementasikan sumber daya sumber daya {private static final string [] servlet_resource_locations = {"/"}; Private Static Final String [] classpath_resource_locations = {"classpath:/meta-inf/sumber daya/", "classpath:/sumber daya/", "classpath:/static/", "classpath:/public/"}; // WebMvAutoconfigurationAdapter @Override public void addViewControllers (viewControllerRegistry registry) {halaman sumber daya = this.resourceProperties.getWelcomePage (); if (halaman! = null) {logger.info ("Menambahkan halaman selamat datang:" + halaman); registry.addviewController ("/"). setViewName ("Forward: index.html"); }} templat
Misalnya, file template halaman dapat ditempatkan di direktori SRC/Main/Resources/Template. Tapi ini sebenarnya ditangani oleh kelas implementasi template itu sendiri. Misalnya, di kelas Thymeleafproperties:
string final public static default_prefix = "classpath:/template/";
jsp
Halaman JSP mirip dengan template. Ini sebenarnya ditangani melalui JSTLView yang dibangun di Spring MVC.
Anda dapat mengonfigurasi spring.view.prefix untuk mengatur direktori halaman JSP:
spring.view.prefix:/web-inf/jsp/
Penanganan halaman kesalahan terpadu di Spring Boot
Untuk halaman kesalahan, Spring Boot juga ditangani secara seragam dengan membuat BasicErrorController.
@Controller@requestMapping ("$ {server.error.path: $ {error.path:/error}}") kelas publik BasicErrorController memperluas abstracterrorcontrollerTampilan yang sesuai adalah pengingat HTML sederhana:
@Configuration@conditionAnproperty (prefix = "server.error.whitelabel", name = "enabled", matchifmissing = true) @conditional (errorTemplateMissingCondition.class) Kelas statis yang dilindungi whitelabelRorViewConfiguration {private final spelview defaulterrorview = spelview final spelview defaulterrorview = spelview final spelview final DefaulterRorView = spelview final spelview final DefaulterRorView = New Spelview DefaulterRorview {private final spelview final DEFAULTERTER FINAL DEFAULTERROW "<html> <body> <h1> halaman kesalahan whitelabel </h1>" + "<p> Aplikasi ini tidak memiliki pemetaan eksplisit untuk/kesalahan, jadi Anda melihat ini sebagai fallback. </p>" + "<div id = 'dibuat'> $ {jadwal waktu} </div>" + "<Div> ada kesalahan yang tidak diekspeksi ($} </div>" + "<Div> ada kesalahan yang tidak diakses ($} </Div>" + " status = $ {status}). </div> " +" <div> $ {message} </div> </body> </html> "); @Bean (name = "error") @ConditionAnonMissingBean (name = "error") Public View DefaulterRorView () {return this.defaulterrorView; }Spring Boot adalah praktik yang baik, yang menghindari pengecualian default yang dilemparkan ketika aplikasi web tradisional membuat kesalahan, membuatnya mudah untuk membocorkan rahasia.
Proses Pengemasan Maven Aplikasi Boot Musim Semi
Pertama, menghasilkan toples yang berisi dependensi melalui Maven-shade-plugin, dan kemudian mengemas kelas yang terkait dengan spring boot loader dan manifest.mf ke dalam toples melalui plugin spring-boot-maven-plugin.
Implementasi Log Warna di Spring Boot
Saat memulai aplikasi Spring Boot di shell, Anda akan menemukan bahwa output loggernya diwarnai, yang sangat menarik.
Pengaturan ini dapat dimatikan:
spring.output.ansi.enabled = false
Prinsipnya adalah untuk mendapatkan konfigurasi ini melalui ansioutputApplicationListener, dan kemudian menetapkan logback ke output, menambahkan colorconverter, dan membuat beberapa bidang melalui org.springframework.boot.ansi.ansioutput.
Beberapa kiat kode
Saat mengimplementasikan ClassLoader, dukung pemuatan paralel JDK7
Anda dapat merujuk ke LockProvider di LaunchedURLClassLoader
Kelas Publik LaunchUrlClassLoader memperluas urlclassloader {private static lockProvider lock_provider = setuplockprovider (); private static lockProvider setuplockProvider () {coba {classloader.registerasparallelcapable (); mengembalikan java7lockprovider () baru; } catch (nosuchmethoderror ex) {return new LockProvider (); }} @Override Protected Class <?> LoadClass (nama string, boolean resolve) melempar ClassNotFoundException {Synchronized (LaunchedUrLClassLoader.Lock_Provider.getLock (this, name)) {class <?> LoadedClass = findloadedclass (name); if (loadedclass == null) {handler.setuseFastConnectionExceptions (true); coba {loadedclass = doloadclass (name); } akhirnya {handler.setusEfastConnectionExceptions (false); }} if (resolve) {resolveClass (loadedclass); } return loadedclass; }} Periksa apakah paket JAR dimuat melalui agen
InputArgumentSjavaAgentDetector, prinsipnya adalah mendeteksi apakah URL toples memiliki awalan "-javaagent:".
string final statis privat java_agent_prefix = "-javaagent:";
Dapatkan PID prosesnya
ApplicationPid, Anda bisa mendapatkan PID.
private string getPid () {coba {string jvmname = ManagementFactory.getRunTimeMxBean (). getName (); return jvmname.split ("@") [0]; } catch (Throwable ex) {return null; }} Kelas Logger Pengemasan
Spring Boot memiliki satu set penebang yang mendukung Java, Log4J, Log4J2, Logback. Anda dapat merujuk ini ketika Anda perlu mengemas penebang Anda sendiri di masa depan.
Di bawah paket org.springframework.boot.logging.
Dapatkan fungsi utama awal yang dimulai
Melalui metode yang diperoleh di tumpukan, menilai fungsi utama dan menemukan fungsi utama yang dimulai.
kelas pribadi <?> deduceMainApplicationClass () {coba {stacktraceElement [] stacktrace = runimeException baru (). getStackTrace (); untuk (StackTraceElement StackTraceElement: Stacktrace) {if ("Main" .Equals (StackTraceElement.GetMethodName ())) {return class.forname (stacktraceElement.getClassName ()); }}} catch (classnotfoundException ex) {// Swallow dan Lanjutkan} return null;} Beberapa kelemahan boot spirng:
Ketika aplikasi Spring Boot berjalan dalam toples gemuk, beberapa masalah akan ditemui. Inilah pendapat pribadi saya:
Meringkaskan
Spring Boot memperluas protokol JAR, abstrak konsep arsip, dan Jarfile pendukung, Jarurlconnection, dan LaunchedURLClassLoader, sehingga menyadari pengalaman pengembangan semua dalam satu tanpa persepsi aplikasi lapisan atas. Meskipun perang yang dapat dieksekusi bukanlah konsep yang diusulkan oleh Spring, Spring Boot memungkinkannya untuk diteruskan.
Spring Boot adalah proyek yang luar biasa, yang dapat dikatakan sebagai musim semi kedua musim semi. Spring-Cloud-Config, Spring-Session, Metrics, Remote Shell, dll. Semua proyek dan fitur yang disukai pengembang. Hampir yakin bahwa perancang memiliki pengalaman yang kaya dalam pengembangan garis depan dan sangat menyadari titik-titik nyeri pengembang.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.