本身写个类加载器

咱们写中间件也好,工具框架也好,写个类加载器是必须的,好比加载指定包下类,加载某个注解标记的类,某个接口的实现类等。框架

定义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

相关文章
相关标签/搜索