从零开始写javaweb框架笔记13-搭建轻量级JAVAWEB框架-开发一个类加载器

来源:互联网 发布:熊猫加速器mac 编辑:程序博客网 时间:2024/05/23 13:11

             我们需要开发一个类加载器,来加载该基础包名下的所有类,比如使用了某注解的类,或实现了某接口的类,在或者继承了某父类的所有子类。

       下一个ClassUtil工具类作为类加载器,提供与类相关的方法,比如获取类加载器,加载类,获取指定包下的所有类。ClassUtil的代码如下:

package org.smart4j.framework.org.smart4j.framework.util;import org.apache.commons.lang3.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.File;import java.io.FileFilter;import java.net.JarURLConnection;import java.net.URL;import java.util.Enumeration;import java.util.HashSet;import java.util.Set;import java.util.jar.JarEntry;import java.util.jar.JarFile;/** * Created by jack on 2017/5/22. * 类操作工具类 */public final class ClassUtil {    private static final Logger LOGGER = LoggerFactory.getLogger(ClassUtil.class);    /**     * 获取类加载器     * 获取加载器类的实现比较简单,只需获取当前线程的ClassLoader     */    public static ClassLoader getClassLoader() {        return Thread.currentThread().getContextClassLoader();    }    /**     * 加载类     * 加载类需要提供类名与是否初始化的标志,这里提到的初始化指是否执行类的静态代码块;     * 为了提高加载类的性能,可以将loadClass方法的isInitialized参数设置false     */    public static Class<?> loadClass(String className, boolean isInitialized) {        Class<?> cls = null;        try {            //进行类加载            cls = Class.forName(className, isInitialized, getClassLoader());        } catch (ClassNotFoundException e) {            LOGGER.error("load class failure.", 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 ("file".equals(protocol)) {                        String packagePath = url.getPath().replace("%20", "");                        addClass(classSet, packagePath, packageName);                    } else if ("jar".equals(protocol)) {                        JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();                        if (jarURLConnection != null) {                            JarFile jarFile = jarURLConnection.getJarFile();                            if (jarFile != null) {                                Enumeration<JarEntry> jarEntries = jarFile.entries();                                while (jarEntries.hasMoreElements()) {                                    JarEntry jarEntry = jarEntries.nextElement();                                    String jarEntryName = jarEntry.getName();                                    if (jarEntryName.endsWith(".class")) {                                        String className = jarEntryName.substring(0, jarEntryName.lastIndexOf("."))                                                .replaceAll("/", ".");                                        doAddClass(classSet, className);                                    }                                }                            }                        }                    }                }            }        } catch (Exception e) {            LOGGER.error("get class set failure.", e);            throw new RuntimeException(e);        }        return classSet;    }    private static void addClass(Set<Class<?>> classSet, String packagePath, String packageName) {        File[] files = new File(packagePath).listFiles(new FileFilter() {            public boolean accept(File file) {                return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();            }        });        for (File file : files) {            String fileName = file.getName();            if (file.isFile()) {                String className = fileName.substring(0, fileName.lastIndexOf("."));                if (StringUtils.isNotEmpty(packageName)) {                    className = packageName + "." + className;                }                doAddClass(classSet, className);            } else {                String subPackagePath = fileName;                if (StringUtils.isNotEmpty(packageName)){                    subPackagePath = packagePath +"/"+subPackagePath;                }                String subPackageName = fileName;                if (StringUtils.isNotEmpty(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);    }}


       我们的目标是在控制器类上使用Controller注解,在控制器类的方法上使用Action注解,在服务类上使用Service注解,在控制器类中可以使用Inject注解将服务依赖注入进来。因此我们需要自定义4个注解类。

       控制器类注解代码如下:

package org.smart4j.framework.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * Created by jack on 2017/5/22. * 控制器注解 */@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Controller {}

      Action方法注解代码如下:

package org.smart4j.framework.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * Created by jack on 2017/5/22. * Action 方法注解 */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface Action {    /**     * 请求路径     */    String value();}


     服务类注解代码如下:

package org.smart4j.framework.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * Created by jack on 2017/5/22. * 服务类注解 */@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Service {}


      依赖注解代码如下:

package org.smart4j.framework.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * Created by jack on 2017/5/22. * 依赖注解类 */@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface Inject {}



    由于我们在smart.properties配置文件中指定了

smart.framework.app.base_package

   他是整个应用的基础包名,所以我们有必要提供一个ClassHelper助手类,让它分别获取应用包名下的所有的类,应用包名下所有的Service类,应用包名下所有的Controller类。此外可以将带有Controller注解和Service注解的类所产生的对象理解为smart框架所管理的bean,所以有必要在ClassHelper类中增加一个获取应用包名下所有bean类的方法,ClassHelper类的代码如下:

     

package org.smart4j.framework.helper;import org.smart4j.framework.annotation.Controller;import org.smart4j.framework.annotation.Service;import org.smart4j.framework.org.smart4j.framework.util.ClassUtil;import java.util.HashSet;import java.util.Set;/** * Created by jack on 2017/5/22. * 类操作助手类 */public class ClassHelper {    /**     * 定义类集合,用于存放所加载的类     */    private static final Set<Class<?>> CLASS_SET;    static {        String basePackage = ConfigHelper.getAppBasePackage();        CLASS_SET = ClassUtil.getClassSet(basePackage);    }    /**     * 获取应用包下的所有类     */    public static Set<Class<?>> getClassSet() {        return CLASS_SET;    }    /**     * 获取应用包名下所有Service类     */    public static Set<Class<?>> getServiceClassSet() {        Set<Class<?>> classSet = new HashSet<Class<?>>();        for (Class<?> cls : CLASS_SET) {            if (cls.isAnnotationPresent(Service.class)) {                classSet.add(cls);            }        }        return classSet;    }    /**     * 获取应用包名下所有Controller类     */    public static Set<Class<?>> getControllerClassSet() {        Set<Class<?>> classSet = new HashSet<Class<?>>();        for (Class<?> cls : CLASS_SET) {            if (cls.isAnnotationPresent(Controller.class)) {                classSet.add(cls);            }        }        return classSet;    }    /**     * 获取应用包名下所有Bean类(包括Service,Controller)     */    public static Set<Class<?>> getBeanClassSet() {       Set<Class<?>> beanClassSet = new HashSet<Class<?>>();       beanClassSet.addAll(getServiceClassSet());       beanClassSet.addAll(getControllerClassSet());        return beanClassSet;    }}


     像上面这样,我们使用ClassHelper封装了ClassUtil,并提供了一系列的助手方法,通过这些方法我们可以直接获取我们想要的类集合,在后面的我们会经常使用到ClassHelper。


阅读全文
1 0
原创粉丝点击