Java利用反射如何查找使用指定注解的类详解

前言

最近有些空,想自己写个跟spring里的注解一样的注解来用,然后希望能找到使用了自己写了注解的类,下面来介绍一下实现方法

声明,下面代码是没看过spring源码写的,基本上都是网上找的博客,整理的

定义注解

Controller.java

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Controller {

}

RequestMapping.java

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestMapping {

 String value();

}

使用注解

@Controller
public class IndexController {

 @RequestMapping("/")
 public void index() {
 System.out.println("index method")
 }

 @RequestMapping("/about")
 public void about(String args) {
 System.out.println("about method")
 }

}

扫描包下所有类

下面这段代码摘自网络博客上的

/**
 * 从包package中获取所有的Class
 *
 * @param packageName
 * @return
 */
public static List<Class<?>> getClasses(String packageName) {

 // 第一个class类的集合
 List<Class<?>> classes = new ArrayList<Class<?>>();
 // 是否循环迭代
 boolean recursive = true;
 // 获取包的名字 并进行替换
 String packageDirName = packageName.replace('.', '/');
 // 定义一个枚举的集合 并进行循环来处理这个目录下的things
 Enumeration<URL> 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");
  // 以文件的方式扫描整个包下的文件 并添加到集合中
  findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);
  } else if ("jar".equals(protocol)) {
  // 如果是jar包文件
  // 定义一个JarFile
  JarFile jar;
  try {
   // 获取jar
   jar = ((JarURLConnection) url.openConnection()).getJarFile();
   // 从此jar包 得到一个枚举类
   Enumeration<JarEntry> 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;
}

传入一个包名,就会自动扫描下面所有的类

找出用了注解的类

//找也用了Controller注解的类
private List<Class<?>> controllers;

public List<Class<?>> getControllers() {
 if (controllers == null) {
 controllers = new ArrayList<>();
 List<Class<?>> clsList = getAllClass();
 if (clsList != null && clsList.size() > 0) {
  for (Class<?> cls : clsList) {
  if (cls.getAnnotation(Controller.class) != null) {
   Map<Class<?>, Object> map = new HashMap<>();
   controllers.add(cls);
  }
  }
 }
 }
 return controllers;
}

查找使用RequestMapping注解的方法,并查出注入的参数

for (Class<?> cls : getControllers()) {
 Method[] methods = cls.getMethods();
 for (Method method : methods) {
 RequestMapping annotation = method.getAnnotation(RequestMapping.class);
 if (annotation != null) {
  String value = annotation.value();//找到RequestMapping的注入value值
  if (value.equals("/about")) {//判断是不是/about,是的话,就调用about(args)方法
  method.invoke(cls.newInstance(), "args"); //第二个参数是方法里的参数
  }
 }
 }
}

这样一来,java项目里用纯servlet写的项目 ,就可以做自己的注解映射路由了,方便极了

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • 浅谈java反射和自定义注解的综合应用实例

    前言 前几天学习了反射和自定义注解,刚好工作中遇到一个小问题:前台传递到后台的必填字段为空,导致不能插入数据库.就是这样一个小问题,让我考虑到是否可以做一个通用的方法,让前台传递过来的必填字段在后台也校验一遍,如果传递为空,则把响应字段返回提示.因此,我考虑的是用注解的方式,在必填字段上面定义,利用反射得到必填字段的字段名,判断是否为空,并返回响应的信息. 需求模拟 假设客户有:姓名,年龄,地址,手机号码,身份证号等信息,而我们是做金融业务,所以关键是看客户的三要素:姓名,身份证号,手机号码.我

  • java基础之反射和泛型以及注解

     java基础之反射和泛型以及注解 泛型擦除 泛型擦除: 泛型只在编译时期有效,编译后的字节码文件中不存在泛型信息. 声明泛型集合,集合两端类型必须一致.类型也可以用包装类型,泛型的类型必须是引用类型,不能为基本类型. 实现公用的类和方法,对公用的业务进行抽取. 泛型方法/泛型类/泛型接口 public class GenericTest { /** * 泛型声明,定义泛型方法 * @param <T> * @param <K> * @param t * @param k */ p

  • Java利用自定义注解、反射实现简单BaseDao实例

    在常见的ORM框架中,大都提供了使用注解方式来实现entity与数据库的映射,这里简单地使用自定义注解与反射来生成可执行的sql语句. 这是整体的目录结构,本来是为复习注解建立的项目^.^ 好的,首先我们来确定思路. 1. 自定义@Table @Column注解, 我们稍微模仿hibernate,让@Table作用于类上,来表明实体类与数据表的映射关系,且让@Table中的属性value映射为数据表的名称tableName:让@Column作用于属性上(这里没实现作用于set方法上),表明属性与

  • Java 自定义注解及利用反射读取注解的实例

    一.自定义注解 元注解: @interface注解: 定义注解接口 @Target注解: 用于约束被描述的注解的使用范围,当被描述的注解超出使用范围则编译失败.如:ElementType.METHOD,ElementType.TYPE: @Retention 注解:用于约束被定义注解的作用范围,作用范围有三个: 1.RetentionPolicy.SOURCE:作用范围是源码,作用于Java文件中,当执行javac时去除该注解. 2.RetentionPolicy.CLASS:作用范围是二进制码

  • 浅谈Java自定义注解和运行时靠反射获取注解

    java自定义注解 Java注解是附加在代码中的一些元信息,用于一些工具在编译.运行时进行解析和使用,起到说明.配置的功能. 注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用.包含在 java.lang.annotation 包中. 1.元注解 元注解是指注解的注解.包括  @Retention @Target @Document @Inherited四种. 1.1.@Retention: 定义注解的保留策略 @Retention(RetentionPolicy.SOURCE) //注解仅

  • java 注解annotation的使用以及反射如何获取注解

     一.注解基本知识 1.元注解 元注解是指注解的注解.包括  @Retention @Target @Document @Inherited四种. 1. Annotation型定义为@interface, 所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口. 2. 参数成员只能用public或默认(default)这两个访问权修饰 3. 参数成员只能用基本类型byte,short,char,int,long,float,doubl

  • Java利用反射如何查找使用指定注解的类详解

    前言 最近有些空,想自己写个跟spring里的注解一样的注解来用,然后希望能找到使用了自己写了注解的类,下面来介绍一下实现方法 声明,下面代码是没看过spring源码写的,基本上都是网上找的博客,整理的 定义注解 Controller.java @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Controller { } RequestMapping.jav

  • C#如何利用反射将枚举绑定到下拉框详解

    前言: 反射(Reflection)是.NET提供给开发者的一个强大工具,尽管作为.NET框架的使用者,很多时候不会用到反射.但在一些情况下,尤其是在开发一些基础框架或公共类库时,使用反射会使系统架构更加灵活. 在开发中,我们常常会遇到比如有些状态值在定义好后几乎从不改动,这时候使用数据库就显得有些多余了.首先想到的一个办法可能是在程序中创建一个数组来表示,此时,我们遇到了使用数组可能带来的第一个问题:不方便使用.当数组结构变更时,可能意味着所有使用过此数组的地方的索引都发生了变更,这是我们不想

  • Java利用反射实现框架类的方法实例

    框架类的简单实现 实现步骤: 1. 加载配置文件 2. 获取配置文件中定义的数据 3. 加载该类进内存 主要讲解第一步:加载配置文件 的相关知识. //1.加载配置文件 //1.1创建Properties对象 Properties pro = new Properties(); //1.2加载配置文件,转换为一个集合 //1.2.1获取class目录下的配置文件 ClassLoader classLoader = ReflectTest.class.getClassLoader(); Input

  • java 利用反射获取内部类静态成员变量的值操作

    昨晚,一同事问到我,怎么利用java反射解析内部类静态成员变量的值,于是顺手写下了. 废话不多说,直接上代码! 待解析类结构如下: /** * @Author changle * @Time 17/6/13. * @Desc to do */ public class Goods { static class apple{ public static String version = "iphone6s[是手机不是吃的苹果]"; public static String date =

  • Java利用反射自动封装成实体对象的方法

    本文实例讲述了Java利用反射自动封装成实体对象的方法.分享给大家供大家参考.具体分析如下: 利用此方法的时候需要传递的参数的名称,必须以行号结尾,去掉行号就是属性名称,比如页面传递name+rowNo,那么实体对象的属性名应该为name.代码如下 复制代码 代码如下: //获取页面数据,自动封装成bean对象 public List getObjectList(Class clazz,String[] rowNos) throws Exception{         List objList

  • Java利用反射获取object的属性和值代码示例

    在看反射顺便做个笔记,目前知道的反射的Object都是要有对象的也就是实体Bean. referance:Java反射简易教程 import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 反射处理Bean,得到里面的属性值 * * @author liulinsen * */ publ

  • Java利用反射实现文件的读取操作

    java反射 java从很早的版本开始就引入了反射机制,java如今的框架底层大部分也都是使用反射实现的. 这篇博客就去探索下java反射使用的方便之处. 要说java的反射机制,肯定离不开Class这个类,我们从jdk的源码可以看到这个类在jdk1.0的时候就存在了. 由于我这边需要用到文件读写的功能,同时又希望写的方法相对来说比较抽象,能在多出直接使用,于是我就想到了java的反射机制. 首先这边先把我的读取文件的方法展示出来 这个是用到的接口类 /** * 实现该接口中的方法,本来打算在F

  • Java利用反射对list对象做过滤

    目录 1.对象结构 2.根据字段名获取value 3.对list过滤 4.精确匹配 5.模糊匹配 ​反射对效率有影响 慎用!!!​ 1.对象结构 public class BusinessDept { private String year;//年 private String month;//月 private String deptName;//部门名称 private String deptLeader;//部门负责人 private Double jyz; //经营值 private D

  • java语言注解基础概念详解

    1.RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃: 2.RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期: 3.RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在: 这3个生命周期分别对应于:Java源文件(.java文件)--->.class文件--->内存中的字节码.

  • java 自定义注解的实例详解

    java  自定义注解的实例详解 Java的Annotation是在5.0版本之后引入的,可以用于创建文档,跟踪代码中的依赖性,并且可以执行编译时期检查.注解就是给虚拟机看的,代表程序的一些特殊的功能.JDK中提供了@Override,@SuppressWarning,@Deprecated三种注解,当让还有元注解,@Target,@Retention,@Documented,@Inherited,元注解的作用负责注解其它注解. 要想了解注解,就要了解自定义注解,了解是通过反射来实现的. 首先,

随机推荐