مقدمة
لتحليل مبدأ بدء التشغيل في Spring Boot نفسه ، يرجى الرجوع إلى: http://www.vevb.com/article/141478.htm
يمكن لعلاقة ميراث ClassLoader في SPRING BOOT تشغيل العرض التوضيحي الوارد أدناه ، وتشغيله في سيناريوهات مختلفة. يمكنك معرفة علاقة وراثة ClassLoader لتطبيقات Boot Spring في سيناريوهات مختلفة.
https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-classloader-context
هناك ثلاث حالات:
في IDE ، تعمل الوظيفة الرئيسية للتشغيل بشكل مباشر على تشغيل spring spring مباشرة. تحتوي عناوين URL الخاصة بـ ClassLoader على جميع الجرار والهدف/الطبقات الخاصة بها
===سف
urls classloader: sun.misc.launcher$ appclasslass@2a139a55
ملف:/المستخدمين/Hengyunabc/Code/Java/Spring-Boot-Inside/Demo-Classloader-Context/Target/Classes/
File: /users/hengyunabc/.m2/repository/org/springframework/cloud/spring-cloud-starter/1.1.9
File: /users/hengyunabc/.m2/repository/org/springframework/boot/spring-boot-starter/1.4.7.release/spring-boot-starter.4.7.Release.jar
...
ركض مثل جرة سمين
MVN Clean PackageJava -jar Target/Demo-Classloader-Context-0.0.1-Snapshot.jar
يتم تشغيل reaftedUrlClasslasserer الذي يقوم بتنفيذ الوظيفة الرئيسية للتطبيق ، وأصله هو نظام تحميل النظام.
=========== Classloader شجرة ================
org.springframework.boot.loader.launchedUrlClassloader@1218025C
- sun.misc.launcher$ appclasslader@6bc7c054
- Sun.Misc.LauncherredExtClasslassloader@85ede7b
LaunchedURLClassLoader的urls هي BOOT-INF/classes!/ الدليل في fat jar وجميع الجرار في Boot-INF/LIB.
===سف
urls classloader: org.springframework.boot.loader.launchedUrlClasslader@1218025C
jar: ملف: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo-classloader-context-0.0.1-snapshot.jar!/boot-inf/classes!
JAR: ملف: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo-classloader-context-0.0.1-snapshot.jar!
JAR: ملف: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo-classloader-context-0.0.1-snapshot.jar! /boot-inf/lib/spring-web-4.3.
...
عناوين URL الخاصة بـ SystemClassLoader هي demo-classloader-context-0.0.1-SNAPSHOT.jar نفسها.
===سف
urls classloader: sun.misc.launcher$ appclasslass@6bc7c054
ملف: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo-classloader-context-0.0.1-snapshot.jar
قم بالتشغيل كدليل مضغوط
MVN Clean Packagecd Targetunzip Demo-Classloader-Context-0.0.1-Snapshot.jar -D DemoCd demojava org.springframework.boot.loader.propertieslauncher
يتم LaunchedURLClassLoader الذي يقوم بتنفيذ الوظيفة الرئيسية للتطبيق ، وأصله هو SystemClassLoader .
=========== Classloader شجرة ================
org.springframework.boot.loader.launchedurlClasslader@4aa298b7
- sun.misc.launcher$ appclasslader@2a139a55
- Sun.Misc.LauncherRedExtClasslassloader@1B6D3586
عناوين URL الخاصة LaunchedURLClassLoader هي حزم الجرة أدناه BOOT-INF/classes/ و /BOOT-INF/lib/ في دليل الضغط.
===سف
urls classloader: org.springframework.boot.loader.launchedurlClasslassloader@4aa298b7
ملف:/المستخدمين/Hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/boot-inf/clistes/
JAR: ملف: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/boot-inf/lib/bcpkix-jdk15on-1.55.jar!/
JAR: ملف: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/boot-inf/lib/bcprov-jdk15on-1.55.jar!/
JAR: ملف: /users/hengyunabc/code/java/spring-boot-inside/demo-classloader-context/target/demo/boot-inf/lib/classmate-1.3.3.jar!/
تحتوي عناوين URL الخاصة بـ SystemClassLoader على الدليل الحالي فقط:
===سف
urls classloader: sun.misc.launcher$ appclasslass@2a139a55
ملف:/المستخدمين/Hengyunabc/Code/Java/Spring-Boot-Inside/Demo-Classloader-Context/Target/Demo/
في الواقع ، هناك طريقتان أخريان للتشغيل: mvn spring-boot:run and mvn spring-boot:run -Dfork=true ، ولكن نادرًا ما يتم استخدامه ولن تتم مناقشته بشكل منفصل. إذا كنت تشعر بالاهتمام ، فيمكنك الركض بنفسك.
ملخص لعلاقة الميراث لـ Classloader في Boot Spring
عندما يتم تنفيذ الوظيفة الرئيسية في IDE ، لا يوجد سوى صنف واحد ، أي SystemClassloader
عند تشغيل جرة سمين ، يوجد reaftureDurlClassloader هو الوالد هو نظام تحميل النظام
عناوين URL الخاصة بـ LaunchedUrlClassloader هي الجرار الموجودة تحت فئات/فئات التمهيد و inf-inf/lib في الجرار الدهنية. عناوين URL الخاصة بـ SystemClassloader هي الجرار الدهنية نفسها.
عند تشغيل الدليل غير المصدفة ، يشبه جرة الدهون ، ولكن عنوان URL في شكل دليل. سيكون لتنسيق الدليل توافق أفضل.
إصدارات التمهيد الربيع 1.3. و 1.4.
في Spring Boot 1.3.* الإصدار
يتم وضع فئة تحميل الحذاء الربيعي في جرة الدهون
تم تقديم تغييرات هيكل التغليف في Spring Boot 1.4 من خلال هذا الالتزام
https://github.com/spring-projects/spring-boot/commit/87feb2adeef85c842c009bfeebac1c84af8a5d7
تتمثل النية الأصلية لهذا الالتزام في تبسيط علاقة الميراث لـ ClassLoader ، وتنفيذ جهاز التشغيل LaunchedUrlClassloader بطريقة أولياء أمور بديهية ، وفي الوقت نفسه ، يكون بنية التغليف أقرب إلى تطبيق حزمة الحرب التقليدية.
ومع ذلك ، تسبب هذا التغيير في العديد من المشاكل المعقدة. من ما سبق قمنا بتحليل علاقة الميراث classloader قليلاً.
بعض تأثيرات علاقة الميراث الحالية
هناك العديد من المستخدمين الذين قد يجدون أن بعض التعليمات البرمجية تعمل بشكل جيد في IDE ولكن لا تعمل عند نشرها بالفعل. في كثير من الأحيان يكون سببها بنية صناديق الفصل. فيما يلي بعض الحالات.
demo.jar!/boot-inf/classes!/بهذه الطريقة لا يعمل عنوان URL
نظرًا لأن SPRING BOOT يمتد بروتوكول JAR القياسي ، مما يسمح له بدعم جرة متعددة الطبقات في جرة ودليل في جرة. ارجع إلى تحليل مبدأ بدء تشغيل تطبيق Boot
على الرغم من أنه سيكون هناك جرة في جرة في Spring Boot 1.3 ، إلا أن بعض التعليمات البرمجية القوية يمكن أن تتعامل مع هذا الموقف ، مثل Tomcat8 نفسها تدعم Jar في Jar.
ومع ذلك ، فإن معظم الكود لن يدعم عناوين URL متعددة مثل demo.jar!/BOOT-INF/classes!/ ، لذلك في Spring Boot1.4 ، ستكون العديد من رموز المكتبة غير صالحة.
قضايا الموارد تحت demo.jar!/meta-inf/الموارد
في مواصفات Servlet 3.0 ، يمكن للتطبيقات أن تضع موارد ثابتة تحت موارد التعريف/الموارد ، وستدعم حاوية Servlet القراءة. ولكن من نتائج الميراث أعلاه ، يمكننا أن نجد مشكلة:
هذا يخلق بعض الظواهر الغريبة:
بالإضافة إلى ذلك ، فإن مثال JSSP الرسمي لـ Spring Boot يدعم فقط تنسيق التغليف في الحرب ولا يدعم جرة الدهون ، والتي تسببها هذا أيضًا.
المشكلات المتعلقة بقيمة الإرجاع لـ GetResource ("") و GetResources ("")
تتمثل دلالات GetResource ("") في إرجاع عنوان URL الأول لعناوين URL ClassLoader. في كثير من الأحيان يعتقد المستخدمون أن هذا هو دليل الفصل الدراسي الخاص بهم ، أو عنوان URL JAR.
ولكن في الواقع ، نظرًا لأن ClassLoader يقوم بتحميل قائمة عناوين URL ، فهي عشوائية ، والتي ترتبط بالتنفيذ منخفض المستوى لنظام التشغيل ، ولا يمكن أن يضمن أن ترتيب URL هو نفسه. لذلك ، فإن النتيجة التي تم إرجاعها بواسطة GetResource ("") غالبًا ما تكون مختلفة.
ومع ذلك ، تعتمد العديد من المكتبات ، أو التطبيقات على هذا الرمز لتحديد موارد المسح ، بحيث لا تعمل تحت Boot Spring.
بالإضافة إلى ذلك ، تجدر الإشارة إلى أن Boot Spring يعمل بثلاثة أشكال مختلفة ، وأن النتائج التي تم إرجاعها بواسطة GetResources ("") مختلفة أيضًا. يمكن للمستخدمين تغيير الرمز في العرض التوضيحي بأنفسهم وطباعة النتائج.
باختصار ، لا تعتمد على هاتين واجهات برمجة التطبيقات ، من الأفضل وضع مورد لتحديد موقعه بنفسك. أو استخدم مباشرة آلية مسح الموارد التي يوفرها Spring نفسها.
مشكلة التصنيف البرية على غرار classpath*: **-service.xml
يحتوي المستخدم على وحدات رمز متعددة ، ويتم وضع ملفات تكوين الربيع المتعددة *service.xml ضمن وحدات مختلفة.
إذا كان المستخدم يستخدم أحرف البرية مثل ClassPath*: **-service.xml لتحميل الموارد ، فمن المحتمل جدًا أن يتم تحميله بشكل صحيح عند التشغيل في IDE ، ولكن لا يمكن تحميله تحت جرة الدهون.
يمكنك رؤية التحليل ذي الصلة من وثائق الربيع الخاصة:
https://docs.spring.io/spring/docs/4.3.9
تحذير: لاحظ أن "classpath:" عندما يتم دمجها مع أنماط النمط النملة ستعمل بشكل موثوق فقط مع دليل جذر واحد على الأقل قبل بدء النمط ، ما لم تكن الملفات المستهدفة الفعلية موجودة في نظام الملفات. هذا يعني أن نمطًا مثل "classpath:*. ينشأ هذا من قيود في طريقة jdk classloader.getResources () التي تُرجع فقط مواقع نظام الملفات لسلسلة فارغة تم تمريرها (تشير إلى جذورها المحتملة للبحث). يحاول تطبيق ResourceStialTerNresolver التخفيف من قيود البحث عن جذر جرة من خلال مقدمة UrlClassloader وتقييم "Java.class.path" ؛ ومع ذلك ، بدون ضمانات قابلية النقل.
وهذا يعني ، عند استخدام ClassPath* لمطابقة حزم الجرة الأخرى ، يجب أن تكون هناك طبقة من الدليل في المقدمة ، وإلا فلن تتطابق معها. يحدث هذا بسبب وظيفة classloader.getResources ().
لأنه عند التشغيل في IDE ، فإن الوحدات الأخرى التي يعتمد عليها التطبيق هي عادة دليل الفئات ، لذلك عادة ما لا توجد مشكلة.
ومع ذلك ، عند التشغيل مع جرة الدهون ، يتم تعبئة وحدات أخرى كجرة ووضعها تحت تشغيل/LIB ، وبالتالي فإن التوزيع البري سيفشل في هذا الوقت.
لخص
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.