获取指定包名下所有的类
来源:互联网 发布:江湖笑歌词.知乎 编辑:程序博客网 时间:2024/05/04 01:12
我们需要开发一个类加载器,来加载该基础包名下的所有类,比如使用了某注解的类,或实现了某接口的类,在或者继承了某父类的所有子类。
Action方法注解代码如下:
下一个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。
阅读全文
0 0
- 获取指定包名下所有的类
- Android中获取指定包名下的所有类
- 获取指定包名下的所有类的类名(全名)
- [Java] 遍历指定包名下所有的类(支持jar)
- Android获取包名下的所有文件
- Java实现类加载器,加载指定包名下的所有类
- 获得指定包名下的所有类全路径(用于遍历包下类)
- 加载指定包名下的所有类或根据类的annotation进行过滤的工具类
- 获取指定包下的所有类
- 怎么实现Spring里面的基于基包名下的所有类的扫描
- ContentProvider跨应用获取data/data/包名下的文件
- Java根据包名获取指定接口的所有实现
- 对于给定指定包名获取所有类
- 对于给定指定包名获取所有类
- 获取一个类的所有指定方法
- 用封装的方法实现从文件夹名下所有的指定类型文件数据导入到数据库
- 获取包下的所有类
- Java 获取包下的所有类
- android 实例 super 什么意思
- h5定位
- 【LeetCode】 Combination Sum 系列
- 配置文件报错:不允许有匹配 "[xX][mM][lL]" 的处理指令目标。
- 安卓四大组件-Service服务
- 获取指定包名下所有的类
- Android四大基本组件
- MATLAB卸载时提示exception calling main的问题
- 多模块Maven(sg-uap)项目部署到tomcat
- 过充保护,过充恢复,过放保护,过放恢复
- android中网络访问学习
- Java+Selenium3.0基础篇2-利用geckodirver启动firefox
- boost C++ read from serial port with timeout example
- 从零开始理解JAVA事件处理机制(1)