- 1.學(xué)習(xí)javapoet 文檔
- 2.學(xué)習(xí)java類(lèi)加載相關(guān)知識(shí)
(1)使用javapoet相關(guān)api 生成一個(gè)類(lèi)
public class CreateJavaFile {
public static void main(String[] args) throws IOException {
//生成一個(gè)方法體(main) 打印輸出一個(gè)hello
MethodSpec methodSpec = MethodSpec.methodBuilder("main")
.addModifiers(Modifier.PUBLIC,Modifier.STATIC)
.returns(void.class)
.addParameter(String[].class,"args")
.addStatement("System.out.println($S)","hello")
.build();
//類(lèi)相關(guān)操作
TypeSpec typeSpec = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC)
.addMethod(methodSpec)//添加一個(gè)方法體
.build();
//包名操作
JavaFile javaFile = JavaFile.builder("com.demo.helloworld",typeSpec).build();
//輸出代碼到控制臺(tái)
javaFile.writeTo(System.out);
//把代碼生成到項(xiàng)目根目錄 文件名為hello
javaFile.writeTo(new File("hello"));
}
}
執(zhí)行完后,得到如下圖幔戏。
(2)新建一個(gè)classLoad類(lèi)繼承URLClassLoader
public class MyClassLoad extends URLClassLoader {
public MyClassLoad(URL[] urls) {
super(urls);
}
@Override
public Class<?> loadClass(java.lang.String name) throws ClassNotFoundException {
System.out.println("loadClass--->"+name);
return super.loadClass(name);
}
@Override
protected Class<?> findClass(java.lang.String name) throws ClassNotFoundException {
System.out.println("findClass--->"+name);
return super.findClass(name);
}
}
(3)測(cè)試婴渡,加載我們生成類(lèi),并調(diào)用方法
public class TestLoadLocalClass {
public static void main(String[] args) throws Exception {
File file = new File("hello");
URL url = file.toURL();
//file.toURL() 方法過(guò)時(shí)可使用 如下代替
//URL url = new URL("file:"+file.getAbsolutePath().replace("\\","/")+"/");
MyClassLoad myClassLoad = new MyClassLoad(new URL[]{url});
//加載類(lèi)文件,包名+類(lèi)名
//只能加載class文件 我們生成的.java文件 需要用 javac 手動(dòng)轉(zhuǎn)換一下
Class aClass = myClassLoad.loadClass("com.demo.helloworld.HelloWorld");
System.out.println(aClass.getClassLoader());
//使用反射得到一個(gè)對(duì)象
Object aObject = aClass.newInstance();
//獲取到main方法,方法的參數(shù)類(lèi)型、個(gè)數(shù)一定要相匹配
Method method = aClass.getMethod("main", String[].class);
//執(zhí)行main方法
method.invoke(aObject, new Object[]{new String[]{}});
}
}
查看classLoad的打印日志,加載類(lèi)到時(shí)候,是先執(zhí)行l(wèi)oadClass 后執(zhí)findClass
loadClass--->com.demo.helloworld.HelloWorld
findClass--->com.demo.helloworld.HelloWorld
loadClass--->java.lang.Object
MyClassLoad@12a3a380 //我們自己建的類(lèi)加載器
loadClass--->java.lang.String
loadClass--->java.lang.System
loadClass--->java.io.PrintStream
hello //輸出類(lèi)hello
Java語(yǔ)言系統(tǒng)自帶有三個(gè)類(lèi)加載器:
- BootstrapClassLoader 最頂層的加載類(lèi),主要加載核心類(lèi)庫(kù)
- ExtentionClassLoader 擴(kuò)展的類(lèi)加載器,加載目錄%JRE_HOME%\lib\ext目錄下的jar包和class文件础浮。
- AppclassLoader也稱(chēng)為SystemAppClass 加載當(dāng)前應(yīng)用的classpath的所有類(lèi)帆调。
(4)進(jìn)入ClassLoader.java 從源碼看java類(lèi)加載機(jī)制
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
// 首先,檢查類(lèi)是否已經(jīng)加載
Class<?> c = findLoadedClass(name);
//如果類(lèi)沒(méi)有被加載過(guò),如果加載過(guò)直接返回類(lèi)豆同,否則先使用父加載加載
if (c == null) {
try {
//如果父加載器不為空則先使用父加載器
//否則使用引導(dǎo)類(lèi)加載器
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
//拋出ClassNotFoundException異常
}
//如果父加載器沒(méi)有找到番刊,則使用調(diào)用自身的findClass
//我們使用的是URLClassLoader,有興趣的話,可以去查看URLClassLoader的findClass()方法
if (c == null) {
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
//返回我們要使用到類(lèi)
return c;
}
}
(5)結(jié)論
類(lèi)加載先從父加載器加載,父類(lèi)沒(méi)有加載到影锈,則使用自身的加載器加載芹务。