前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >自己写个类加载器

自己写个类加载器

作者头像
春哥大魔王
发布2018-07-23 11:27:43
3990
发布2018-07-23 11:27:43
举报

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

(如果代码阅读体验不好,可以点击阅读原文,进入博客阅读)

定义ClassUtil工具类,提供基本操作:

代码语言:javascript
复制
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包,再去进行类加载:

代码语言:javascript
复制
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)启动时进行类加载:

代码语言:javascript
复制
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;
} 

这样我们一个自定义的类加载器就搞定了,后续我们会结合到业务中去使用。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-05-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 春哥talk 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档