首页 Java java教程 获取指定包下所有自定义注解

获取指定包下所有自定义注解

Jun 23, 2017 pm 03:26 PM
指定 注解 自定义 获取

Reflections 通过扫描 classpath,索引元数据,允许在运行时查询这些元数据,也可以保存收集项目中多个模块的元数据信息。

使用Reflections快速扫描指定包下自定义的Controller和RequestMapping两个注解,先去扫描加了@Controller注解的类,接着获取这些类下面加了@RequestMapping注解的方法,然后通过Java的反射invoke方法去调用加了RequestMapping注解的方法并输出注解上的信息。

Maven 项目导入

<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.10</version>
</dependency>
登录后复制

annotation包下面自定义了两个注解。

Controller.java:

package annotationTest.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)// 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)//定义注解的作用目标**作用范围字段、枚举的常量/方法
@Documented//说明该注解将被包含在javadoc中
public @interface Controller {
    String value() default "";
}
登录后复制

RequestMapping.java

package annotationTest.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
    String value() default "";

    /**
     * 是否为序列号
     *
     * @return
     */
    boolean id() default false;

    /**
     * 字段名称
     *
     * @return
     */
    String name() default "";

    /**
     * 字段描述
     *
     * @return
     */
    String description() default "";
}
登录后复制

在model包下面定义了一个存放RequestMapping注解方法的对象

ExecutorBean.java

package annotationTest.model;

import java.lang.reflect.Method;

public class ExecutorBean {
    private Object object;

    private Method method;

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }
}
登录后复制

service包下面定义了几个类,其中有两个类使用了自定义的Controller注解

SunService.java

package annotationTest.service;

import annotationTest.annotation.Controller;
import annotationTest.annotation.RequestMapping;

@Controller
public class SunService {
    @RequestMapping(id = true, name = "test1", description = "sun测试1", value = "/test1")
    public void test1() {
        System.out.println("SunService->test1()");
    }

    @RequestMapping(id = true, name = "test2", description = "sun测试2", value = "/test2")
    public void test2() {
        System.out.println("SunService->test2()");
    }
}
登录后复制

MoonService.java

package annotationTest.service;

import annotationTest.annotation.Controller;
import annotationTest.annotation.RequestMapping;

@Controller
public class MoonService {
    @RequestMapping(id = true, name = "moon测试3", description = "/test3", value = "/test3")
    public void test3() {
        System.out.println("MoonService->test3()");
    }

    @RequestMapping(id = true, name = "moon测试4", description = "/test4", value = "/test4")
    public void test4() {
        System.out.println("MoonService->test4()");
    }
}
登录后复制

Stars.java

package annotationTest.service;

import annotationTest.annotation.RequestMapping;

public class Stars {
    @RequestMapping(id = true, name = "test1", description = "stars测试1", value = "/test1")
    public void test1() {
        System.out.println("Stars->test1()");
    }
}
登录后复制

util包下面定义了一个工具类,来对包进行扫描获取自定义注解的类和方法

AnnoManageUtil.java

package annotationTest.util;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import annotationTest.annotation.Controller;
import annotationTest.annotation.RequestMapping;
import annotationTest.model.ExecutorBean;
import org.reflections.Reflections;

public final class AnnoManageUtil {

    /**
     * 获取指定文件下面的RequestMapping方法保存在mapp中
     *
     * @param packageName
     * @return
     */
    public static Map<String, ExecutorBean> getRequestMappingMethod(String packageName) {
        Reflections reflections = new Reflections(packageName);
        Set<Class<?>> classesList = reflections.getTypesAnnotatedWith(Controller.class);

        // 存放url和ExecutorBean的对应关系
        Map<String, ExecutorBean> mapp = new HashMap<String, ExecutorBean>();
        for (Class classes : classesList) {
            //得到该类下面的所有方法
            Method[] methods = classes.getDeclaredMethods();

            for (Method method : methods) {
                //得到该类下面的RequestMapping注解
                RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
                if (null != requestMapping) {
                    ExecutorBean executorBean = new ExecutorBean();
                    try {
                        executorBean.setObject(classes.newInstance());
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    executorBean.setMethod(method);
                    mapp.put(requestMapping.value(), executorBean);

                }
            }
        }
        return mapp;
    }

}
登录后复制

test包下面是一个测试的类

package annotationTest.test;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import annotationTest.annotation.Controller;
import annotationTest.annotation.RequestMapping;
import annotationTest.model.ExecutorBean;
import annotationTest.util.AnnoManageUtil;

public class Test {
    public static void main(String[] args) {
        List<Class<?>> classesList = null;
        classesList = AnnoManageUtil.getPackageController("annotationTest.service", Controller.class);
        Map<String, ExecutorBean> mmap = new HashMap<String, ExecutorBean>();
        AnnoManageUtil.getRequestMappingMethod(classesList, mmap);
        ExecutorBean bean = mmap.get("/test1");

        try {
            bean.getMethod().invoke(bean.getObject());
            RequestMapping annotation = bean.getMethod().getAnnotation(RequestMapping.class);
            System.out.println("注解名称:" + annotation.name() + "\t注解描述:" + annotation.description());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
登录后复制

运行得到:

获取指定包下所有自定义注解

其他

  1. 使用 Reflections 可以查询以下元数据信息:

    Reflections 依赖 Google 的 Guava 库和 Javassist 库。

  • 获得某个类型的所有子类型

  • 获得标记了某个注解的所有类型/成员变量,支持注解参数匹配。

  • 使用正则表达式获得所有匹配的资源文件

  • 获得所有特定签名(包括参数,参数注解,返回值)的方法

  • 使用注解修饰了类/方法/成员变量等之后,这些注解不会自己生效,必须由这些注解的开发者提供相应的工具来提取并处理注解信息(当然,只有当定义注解时使用了@Retention(RetentionPolicy.RUNTIME)修饰,JVM才会在装载class文件时提取保存在class文件中的注解,该注解才会在运行时可见,这样我们才能够解析).

  • Java使用Annotation接口来代表程序元素前面的注解,该接口是所有注解的父接口。

  • java5在java.lang.reflect包下新增了 用AnnotatedElement接口代表程序中可以接受注解的程序元素.

  • AnnotatedElement接口的实现类有:Class(类元素)、Field(类的成员变量元素)、Method(类的方法元素)、Package(包元素),每一个实现类代表了一个可以接受注解的程序元素类型。

  • 这样, 我们只需要获取到Class、 Method、 Filed等这些实现了AnnotatedElement接口的类的实例,通过该实例对象调用该类中的方法(AnnotatedElement接口中抽象方法的重写) 就可以获取到我们想要的注解信息了。

  • 获得Class类的实例有三种方法:

    • 利用对象调用getClass()方法获得Class实例

    • 利用Class类的静态的forName()方法,使用类名获得Class实例

    • 运用.class的方式获得Class实例,如:类名.class

  • AnnotatedElement接口提供的抽象方法(在该接口的实现类中重写了这些方法):

    • T getAnnotation(Class< T> annotationClass)< T extends Annotation>为泛型参数声明,表明A的类型只能是Annotation类型或者是Annotation的子类。
      功能:返回该程序元素上存在的、指定类型的注解,如果该类型的注解不存在,则返回null

    • Annotation[] getAnnotations()
      功能:返回此元素上存在的所有注解,包括没有显示定义在该元素上的注解(继承得到的)。(如果此元素没有注释,则返回长度为零的数组。)

    • < T extends Annotation> T getDeclaredAnnotation(Class < T> annotationClass)
      功能:这是Java8新增的方法,该方法返回直接修饰该程序元素、指定类型的注解(忽略继承的注解)。如果该类型的注解不存在,返回null.

    • Annotation[] getDeclaredAnnotations()
      功能:返回直接存在于此元素上的所有注解,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)

    • boolean isAnnotationPresent(Class annotationClass)
      功能:判断该程序元素上是否存在指定类型的注解,如果存在则返回true,否则返回false。

    • <T extends Annotation> T[] getAnnotationsByTpye(Class annotationClass)
      功能: 因为java8增加了重复注解功能,因此需要使用该方法获得修饰该程序元素、指定类型的多个注解。

    • T[] getDeclaredAnnotationsByTpye(ClassannotationClass)
      功能: 因为java8增加了重复注解功能,因此需要使用该方法获得直接修饰该程序元素、指定类型的多个注解。

    Class提供了getMethod()、getField()以及getConstructor()方法(还有其他方法),这些方法分别获取与方法、域变量以及构造函数相关的信息,这些方法返回Method、Field 以及Constructor类型的对象。

    以上是获取指定包下所有自定义注解的详细内容。更多信息请关注PHP中文网其他相关文章!

    本站声明
    本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

    热AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智能驱动的应用程序,用于创建逼真的裸体照片

    AI Clothes Remover

    AI Clothes Remover

    用于从照片中去除衣服的在线人工智能工具。

    Undress AI Tool

    Undress AI Tool

    免费脱衣服图片

    Clothoff.io

    Clothoff.io

    AI脱衣机

    AI Hentai Generator

    AI Hentai Generator

    免费生成ai无尽的。

    热门文章

    R.E.P.O.能量晶体解释及其做什么(黄色晶体)
    1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.最佳图形设置
    1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.如果您听不到任何人,如何修复音频
    1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.聊天命令以及如何使用它们
    1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

    热工具

    记事本++7.3.1

    记事本++7.3.1

    好用且免费的代码编辑器

    SublimeText3汉化版

    SublimeText3汉化版

    中文版,非常好用

    禅工作室 13.0.1

    禅工作室 13.0.1

    功能强大的PHP集成开发环境

    Dreamweaver CS6

    Dreamweaver CS6

    视觉化网页开发工具

    SublimeText3 Mac版

    SublimeText3 Mac版

    神级代码编辑软件(SublimeText3)

    如何在Netflix中快速设置自定义头像 如何在Netflix中快速设置自定义头像 Feb 19, 2024 pm 06:33 PM

    Netflix上的头像是你流媒体身份的可视化代表。用户可以超越默认的头像来展示自己的个性。继续阅读这篇文章,了解如何在Netflix应用程序中设置自定义个人资料图片。如何在Netflix中快速设置自定义头像在Netflix中,没有内置功能来设置个人资料图片。不过,您可以通过在浏览器上安装Netflix扩展来实现此目的。首先,在浏览器上安装Netflix扩展的自定义个人资料图片。你可以在Chrome商店买到它。安装扩展后,在浏览器上打开Netflix并登录您的帐户。导航至右上角的个人资料,然后单击

    Eclipse中自定义快捷键设置的方法 Eclipse中自定义快捷键设置的方法 Jan 28, 2024 am 10:01 AM

    如何在Eclipse中自定义快捷键设置?作为一名开发人员,在使用Eclipse进行编码时,熟练掌握快捷键是提高效率的关键之一。Eclipse作为一款强大的集成开发环境,不仅提供了许多默认的快捷键,还允许用户根据自己的偏好进行个性化的定制。本文将介绍如何在Eclipse中自定义快捷键设置,并给出具体的代码示例。打开Eclipse首先,打开Eclipse,并进入

    谷歌安全码在哪里获取 谷歌安全码在哪里获取 Mar 30, 2024 am 11:11 AM

    谷歌验证器是一种用于保护用户账户安全的工具,其密钥是用于生成动态验证码的重要信息。如果忘记了谷歌验证器的密钥,只能通过安全码进行验证,那么下文本站小编就将为大家带来谷歌安全码在哪里获取的详细内容介绍,希望能帮助到大家,想要了解的用户们就请跟着下文继阅读吧!首先打开手机设置,进入设置页面。下拉页面,找到Google。进入Google页面,点击Google账号。进入账号页面,点击验证码下方的查看。输入密码或者使用指纹验证身份。获得Google安全码,利用安全码验证谷歌身份。

    JUnit框架中注解如何用于测试方法? JUnit框架中注解如何用于测试方法? May 06, 2024 pm 05:33 PM

    JUnit框架中的注解用于声明和配置测试方法,主要注解包括:@Test(声明测试方法)、@Before(测试方法执行前运行的方法)、@After(测试方法执行后运行的方法)、@BeforeClass(所有测试方法执行前运行的方法)、@AfterClass(所有测试方法执行后运行的方法),这些注解有助于组织和简化测试代码,并通过提供明确的意图和配置来提高测试代码的可读性和可维护性。

    PHP 代码文档化之王:PHPDoc 的进阶指南 PHP 代码文档化之王:PHPDoc 的进阶指南 Mar 02, 2024 am 08:43 AM

    引言:PHPDoc是一种用于php代码的注释标准,可生成易于理解且信息丰富的文档。通过使用特定的注释标签,PHPDoc允许开发人员提供有关函数、类、方法和其他代码元素的重要详细信息。这篇进阶指南将深入探讨PHPDoc,展示其功能并提供有效的文档化策略。语法和标签:PHPDoc注释以双斜杠(//)或多行注释(/**/)开头。以下是一些常见的注释标签:@param:定义函数或方法的参数。@return:指定函数或方法的返回值。@throws:说明函数或方法可能引发的异常。@var:定义类的属性或实例

    edius自定义屏幕布局的操作流程 edius自定义屏幕布局的操作流程 Mar 27, 2024 pm 06:50 PM

    1、下图是edius默认的屏幕布局,默认的EDIUS窗口布局是横向版式,因此在单显示器环境中,许多窗口是重叠在一起的,且预览窗口为单窗口模式。2、您可以通过【视图】菜单栏启用【双窗口模式】,使预览窗口同时显示播放窗口和录制窗口。3、您可以通过【视图菜单栏>窗口布局>常规】来恢复默认屏幕布局。另外您还可以自定义适合您的布局方式,并保存为常用屏幕布局:将窗口拖动成适合自己的布局,然后点击【视图>窗口布局>保存当前布局>新建】,在弹出的【保存当前布局】小窗口中输入布局名称,单击确定

    Jackson库中注解如何控制JSON序列化和反序列化? Jackson库中注解如何控制JSON序列化和反序列化? May 06, 2024 pm 10:09 PM

    Jackson库中的注解可控制JSON序列化和反序列化:序列化:@JsonIgnore:忽略属性@JsonProperty:指定名称@JsonGetter:使用获取方法@JsonSetter:使用设置方法反序列化:@JsonIgnoreProperties:忽略属性@JsonProperty:指定名称@JsonCreator:使用构造函数@JsonDeserialize:自定义逻辑

    详解MyBatis注解与动态SQL的操作步骤 详解MyBatis注解与动态SQL的操作步骤 Feb 18, 2024 pm 03:29 PM

    MyBatis注解动态SQL的使用方法详解IntroductiontotheusageofMyBatisannotationdynamicSQLMyBatis是一个持久层框架,为我们提供了便捷的持久化操作。在实际开发中,通常需要根据业务需求来动态生成SQL语句,以实现灵活的数据操作。MyBatis注解动态SQL正是为了满足这一需求而设计的,本

    See all articles