栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java获取包下被指定注解的类过程解析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java获取包下被指定注解的类过程解析

方案一: 采用reflections 框架(此框架依赖com.google.guava)

1、reflections框架地址:https://github.com/ronmamo/reflections

2、项目依赖


      org.reflections
      reflections
      0.9.11
    

     com.google.guava guava
      21.0
    

3、实现代码

//入参 要扫描的包名
Reflections f = new Reflections("com.ggband.netty.execute.command");
//入参 目标注解类
Set> set = f.getTypesAnnotatedWith(Cmd.class);

方案二: 采用ClassLoader扫描

1、实现代码

package com.ggband.netty;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class Scanner {
  
  public Set> getClasses(String packageName) throws Exception {

    // 第一个class类的集合
    //List> classes = new ArrayList>();
    Set> classes = new HashSet<>();
    // 是否循环迭代
    boolean recursive = true;
    // 获取包的名字 并进行替换
    String packageDirName = packageName.replace('.', '/');
    // 定义一个枚举的集合 并进行循环来处理这个目录下的things
    Enumeration dirs;
    try {
      dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
      // 循环迭代下去
      while (dirs.hasMoreElements()) {
 // 获取下一个元素
 URL url = dirs.nextElement();
 // 得到协议的名称
 String protocol = url.getProtocol();
 // 如果是以文件的形式保存在服务器上
 if ("file".equals(protocol)) {
   // 获取包的物理路径
   String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
   // 以文件的方式扫描整个包下的文件 并添加到集合中
   addClass(classes, filePath, packageName);
 } else if ("jar".equals(protocol)) {
   // 如果是jar包文件
   // 定义一个JarFile
   JarFile jar;
   try {
     // 获取jar
     jar = ((JarURLConnection) url.openConnection()).getJarFile();
     // 从此jar包 得到一个枚举类
     Enumeration entries = jar.entries();
     // 同样的进行循环迭代
     while (entries.hasMoreElements()) {
// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如meta-INF等文件
JarEntry entry = entries.nextElement();
String name = entry.getName();
// 如果是以/开头的
if (name.charAt(0) == '/') {
  // 获取后面的字符串
  name = name.substring(1);
}
// 如果前半部分和定义的包名相同
if (name.startsWith(packageDirName)) {
  int idx = name.lastIndexOf('/');
  // 如果以"/"结尾 是一个包
  if (idx != -1) {
    // 获取包名 把"/"替换成"."
    packageName = name.substring(0, idx).replace('/', '.');
  }
  // 如果可以迭代下去 并且是一个包
  if ((idx != -1) || recursive) {
    // 如果是一个.class文件 而且不是目录
    if (name.endsWith(".class") && !entry.isDirectory()) {
      // 去掉后面的".class" 获取真正的类名
      String className = name.substring(packageName.length() + 1, name.length() - 6);
      try {
 // 添加到classes
 classes.add(Class.forName(packageName + '.' + className));
      } catch (ClassNotFoundException e) {
 e.printStackTrace();
      }
    }
  }
}
     }
   } catch (IOException e) {
     e.printStackTrace();
   }
 }
      }
    } catch (IOException e) {
      e.printStackTrace();
    }

    return classes;
  }

  public void addClass(Set> classes, String filePath, String packageName) throws Exception {
    File[] files = new File(filePath).listFiles(file -> (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory());
    assert files != null;
    for (File file : files) {
      String fileName = file.getName();
      if (file.isFile()) {
 String classsName = fileName.substring(0, fileName.lastIndexOf("."));
 if (!packageName.isEmpty()) {
   classsName = packageName + "." + classsName;
 }
 doAddClass(classes, classsName);
      }

    }
  }

  public void doAddClass(Set> classes, final String classsName) throws Exception {
    ClassLoader classLoader = new ClassLoader() {
      @Override
      public Class loadClass(String name) throws ClassNotFoundException {
 return super.loadClass(name);
      }
    };
    classes.add(classLoader.loadClass(classsName));
  }


  public  Set> getAnnotationClasses(String packageName, Class annotationClass) throws Exception {

    //找用了annotationClass注解的类
    Set> controllers = new HashSet<>();
    Set> clsList = getClasses(packageName);
    if (clsList != null && clsList.size() > 0) {
      for (Class cls : clsList) {
 if (cls.getAnnotation(annotationClass) != null) {
   controllers.add(cls);
 }
      }
    }
    return controllers;
  }


}

2、使用:

 Set> set = new Scanner().getAnnotationClasses("com.ggband.netty.execute.command", Cmd.class);

扩充:现在就可以实现自己的业务了,比如 扫描com.ggband.netty.execute.command包下被Cmd注解的类 得到Cmd注解value和被注解类的实例

Map beanContainer = new HashMap<>();
    try {
      //@1 采用reflections 框架(此框架依赖com.google.guava)
//Reflections f = new Reflections("com.ggband.netty.execute.command");
//Set> set = f.getTypesAnnotatedWith(Cmd.class);
      //@2 采用ClassLoader扫描
      Set> set = new Scanner().getAnnotationClasses("com.ggband.netty.execute.command", Cmd.class);
      for (Class c : set) {
 Object bean = c.newInstance();
 Cmd annotation = c.getAnnotation(Cmd.class);
 beanContainer.put(Arrays.toString(annotation.value()), (Command) bean);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/136734.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号