這個你們熟悉,加載機制,雙親委派。
JAVA啓動時,會初始化3個類加載器,BootClassLoader,ExtClassLoader,AppClassLoader。
BootClassLoader 加載jre/lib下的JAR包,由C++實現。 ExtClassLoader 加載jre/lib/ext下的JAR包,其父加載器爲BootClassLoader。 AppClassLoader 加載classpath下的JAR包,也稱用戶加載器。其父加載器爲ExtClassLoader。java
經常使用的自定義類加載器爲tomcat,spring-boot會有本身的類加器。 咱們如今本身實一個類加載器,從e:/arthas目錄下加載class。類加載器除了加載Class還有一個主要功能,那就是加載資源。這裏咱們簡單一點,直接繼承URLClassLoader。若是要本身作的話,那就繼承ClassLoader,而後重寫findClass和findResource方法。spring
public class B { public static void main(String[] args) throws InterruptedException { FileClassLoad fileClassLoad = new FileClassLoad(); try { Class clazz = fileClassLoad.loadClass("spring.B1"); System.out.println(clazz); clazz.newInstance(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } } }
public class B1 { public B1(){ B2 b2 = new B2(); b2.say(); } }
public class B2 { public void say(){ URL url = this.getClass().getResource("test.txt"); System.out.println(url); System.out.println(B2.class.getClassLoader()); } }
public class FileClassLoad extends URLClassLoader { private static URL[] urls = null; static{ try { File file = new File("E://arthas/"); urls = new URL[1]; urls[0]=file.toURI().toURL(); } catch (MalformedURLException e) { e.printStackTrace(); } } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { System.out.println(name); return super.findClass(name); } public FileClassLoad(){ super(urls); } }
編譯,將它從class目錄下移除,若是不移除的話,執行後,不會用到咱們的自定義加載器,那test.txt將會獲取不到。這就是雙親,先從父加載器加載,父加載器加載不到,再從當前加載器進行加載。
將B1.class B2.class按包結構考備到e:/arthas目錄下,而且建立test.txt。 運行,結果以下:tomcat
spring.B1 class spring.B1 spring.B2 file:/E:/arthas/spring/test.txt //經過FileClassLoader加載的資源 spring.FileClassLoad@5b2133b1 //B2.class 採用的是咱們自定義的加載器,這裏是委派,用B1的加載器加載B2
有了這些基礎再去看spring-boot的類加載器,就比較方便了。另外spring-boot會什麼要用本身的類加載器。答案很簡單。spring-boot打出來的JAR裏面包含boot-info目錄,在該目錄下還有jar包和class。spring-boot自定義加載器就是須要加載該目錄下的JAR和資源。同裏tomcat也是,它也有本身特定格式下的資源,好比war包。ide