本身寫個類加載器

咱們寫中間件也好,工具框架也好,寫個類加載器是必須的,好比加載指定包下類,加載某個註解標記的類,某個接口的實現類等。框架

定義ClassUtil工具類,提供基本操做:ide

public final class Classutil{

	/*
		獲取類加載器
	*/
	public static ClassLoader getClassLoader(){
		return Thread.currentThread().getContextClassLoader();
	}

        // 爲提高性能,isInitialized默認爲false
	public static Class<?> loadClass(String className, boolean isInitialized){
		Class<?> cls;
		try{
			cls = Class.forName(className,isInitialized,getClassLoader());
		}catch(ClassNotFoundException e){
			throw new RuntimeException(e);
		}
		return cls;
	}

}

獲取指定包下全部的類,須要將包名轉換爲文件路徑,讀class文件或者jar包,再去進行類加載:工具

public static Set<Class<?>> getClassSet(String packageName){
    Set<Class<?>> classSet = new HashSet<Class<?>>();
    try{
        Enumeration<URL> urls = getClassLoader().getResources(packageName.replace(".","/"));
        while(urls.hasMoreElements()){
            URL url = urls.nextElement();
            if(url != null){
                String protocol = url.getProtocol();
                if(protocol.equals("file")){
                    String packagePath = url.getPath().replaceAll("%20","");
                    addClass(classSet,packagePath,packageName);
                }else if (protocol.equals("jar")){
                    JarURLConnection jarURLConnection = (JarURLConnection)url.openConnection();
                    if(jarURLConnection != null){
                        JarFile jarFile = jarURLConnection.getJarFile();
                        if(jarFile != null){
                            Enumeration<JarEntity> jarEntities = jarFile.entries();
                            while(jarEntries.hasMoreElements()){
                                JarEntity jarEntity = jarEntities.nextElement();
                                String jarEntityName = jarEntity.getName();
                                if(jarEntityName.endWith(".class")){
                                    String className = jarEntryName.substring(0,jarEntryName.lastIndexOf(".")).replaceAll("/",".");
                                    doAddClass(classSet,ClassName);
                                }
                            }
                        }
                    }
                }
            }
        }
    }catch(Exception e){
        throw new RuntimeException(e);
    }
    return classSet;
}

private static void addClass(Set<Class<?>> classSet, String packagePath, String packageName){
    File[] files = new File(packagePaht).listFiles(new FileFilter(){
        @Override
        public boolean accept(File file){
            return (file.isFie() && file.getName().endWith(".class")) || file.isDirectory();
        }
    });
    
    for(File file:files){
        String fileName = file.getName();
        if(file.isFile()){
            Stirng className = fileName.substring(0,fileName.lastIndexOf("."));
            if(!StringUtils.isBlank(packageName)){
                className = packageName + "."+className;
            }
            doAddClass(classSet, className);
        }else{
            String subPackagePath = fileName;
            if(!StringUtils.isBlank(packagePath)){
                subPackagePath = packagePath + "/"+subPackagePath;
            }
            String subPackageName = fileName;
            if(!StringUtils.isBlank(packageName)){
                subPackageName = packageName + "."+subPackageName;
            }
            addClass(classSet,subPackagePath,subPackageName);
        }
    }
}

private static void doAddClass(Set<Class<?>> classSet, String className){
    Class<?> cls = loadClass(className, false);
    classSet.add(cls);
}

在容器(好比Spring)啓動時進行類加載:性能

private static Set<Class<?>> CLASS_SET;

public static void init(String basePackage){
    CLASS_SET = ClassBuilder.getClassSet(basePackage);
}
/* 獲取包下全部的類 */
public static Set<Class<?>> getClassSet(){
    return CLASS_SET;
}
/* 獲取包下全部指定註解的類 */
pubic static Set<Class<?>> getAnnoClassSet<Class<?> extends Annotation annoClass>{
    Set<Class<?>> classSet = new HashSet<>();
    for(Class<?> cls : CLASS_SET){
        if(cls.isAnnotationPresent(annoClass)){
            classSet.add(cls);
        }
    }
    return classSet;
}

這樣咱們一個自定義的類加載器就搞定了,後續咱們會結合到業務中去使用。ui

相關文章
相關標籤/搜索