Java基础教程——解析注解
解析注解
Java 5开始,java.lang.reflect包下的反射API可以在运行时读取Annotation。
应用:定义一个自动执行方法的注解,解析注解、通过反射执行方法,替代配置文件。
package ah.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//==============================================
//注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface AutoMethod {
String className();
String methodName();
}
// ==============================================
// 想要调用的类和方法
class Cat {
public void show() {
System.out.println("Cat show");
}
}
// ==============================================
// 测试类
@AutoMethod(className = "ah.annotation.Cat", methodName = "show")
public class TestParseAnn {
public static void main(String[] args) {
// 1.获取类的字节码对象
Class<TestParseAnn> cls = TestParseAnn.class;
// 2.获取注解对象
AutoMethod ann = cls.getAnnotation(AutoMethod.class);
// 3.调用注解对象的抽象方法,获取返回值
String className = ann.className();
String methodName = ann.methodName();
System.out.println("获取到类名:" + className);
System.out.println("获取到方法名:" + methodName);
// 使用反射集合调用方法(略)
}
}
获取到类名:ah.annotation.Cat
获取到方法名:show
例:使用注解进行方法测试
注解传入的变量:B
方法public static void ah.AnnoTestExample.m3(java.lang.String)运行失败,异常:java.lang.IllegalArgumentException: 参数出错!
注解传入的变量:御弟
--m1--:御弟
共运行了:2个方法,其中:
失败了:1个,
成功了:1个!
package ah.annotation;
import java.lang.annotation.*;
import java.lang.reflect.Method;
//============================================
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@Inherited
@interface AnnoTest {
// 注解的属性:
String name() default "御弟";
}
// ============================================
// 使用自定义注解的类
class AnnoTestExample {
@AnnoTest
public static void m1(String _name) {
System.out.println("--m1--:" + _name);
}
public static void m2() {
System.out.println("这个方法不测试");
}
@AnnoTest(name = "B")
public static void m3(String _name) {
if (_name.equals("B")) {
throw new IllegalArgumentException("参数出错!");
} else {
System.out.println("--m3--:" + _name);
}
}
}
// ============================================
// APT:Annotation Processor Test(注解处理工具)
class APT {
public static void process(String className) throws ClassNotFoundException {
int passed = 0;
int failed = 0;
Class<?> _class = Class.forName(className);
for (Method m : _class.getMethods()) {
// 如果该方法使用了@注解
if (m.isAnnotationPresent(AnnoTest.class)) {
// 获取注解中的变量
AnnoTest ann = m.getAnnotation(AnnoTest.class);
String name = ann.name();
System.out.println(" 注解传入的变量:" + name);
try {
// 调用m方法
m.invoke(_class, name);
// *方法无参数可直接传入null:
// m.invoke(null);
// 测试成功,passed计数器加1
passed++;
} catch (Exception ex) {
System.out.println("方法" + m + "运行失败,异常:" + ex.getCause());
// 测试出现异常,failed计数器加1
failed++;
}
}
}
// 统计测试结果
System.out.println("共运行了:" + (passed + failed) + "个方法,其中:\n" + "失败了:"
+ failed + "个,\n" + "成功了:" + passed + "个!");
}
}
/**
* 测试类,主方法
*/
public class TestMyAnnotation {
public static void main(String[] args) throws ClassNotFoundException {
String _包类名 = "ah.annotation.AnnoTestExample";
APT.process(_包类名);
}
}
注解传入的变量:B
方法public static void ah.annotation.AnnoTestExample.m3(java.lang.String)运行失败,异常:java.lang.IllegalArgumentException: 参数出错!
注解传入的变量:御弟
--m1--:御弟
共运行了:2个方法,其中:
失败了:1个,
成功了:1个!
Java基础教程——解析注解的更多相关文章
- Java基础教程:注解
Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...
- Java基础教程(16)--注解
一.注解基础知识 1.注解的格式 最简单的注解就像下面这样: @Entity @符号指示编译器其后面的内容是注解.在下面的例子中,注解的名称为Override: @Override void ...
- Java基础教程(18)--继承
一.继承的概念 继承是面向对象中一个非常重要的概念,使用继承可以从逻辑和层次上更好地组织代码,大大提高代码的复用性.在Java中,继承可以使得子类具有父类的属性和方法或者重新定义.追加属性和方法. ...
- Java基础教程(25)--I/O
一.I/O流 I/O流表示输入源或输出目标.流可以表示许多不同类型的源和目标,例如磁盘文件.设备.其他程序等. 流支持许多不同类型的数据,包括字节.原始数据类型.字符和对象等.有些流只传递数据 ...
- Java基础教程:IDEA单元测试
Java基础教程:IDEA单元测试 环境配置 使用idea IDE 进行单元测试,首先需要安装JUnit 插件. 安装JUnit插件步骤 File-->settings-->Plguins ...
- Java基础笔记 – Annotation注解的介绍和使用 自定义注解
Java基础笔记 – Annotation注解的介绍和使用 自定义注解 本文由arthinking发表于5年前 | Java基础 | 评论数 7 | 被围观 25,969 views+ 1.Anno ...
- Java基础教程(12)--深入理解类
一.方法的返回值 当我们在程序中调用方法时,虚拟机将会跳转到对应的方法中去执行.当以下几种情况发生时,虚拟机将会回到调用方法的语句并继续向下执行: 执行完方法中所有的语句: 遇到return语句: ...
- Java基础教程:网络编程
Java基础教程:网络编程 基础 Socket与ServerSocket Socket又称"套接字",网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个s ...
- Java基础教程(5)--变量
一.变量 1.变量的定义 正如上一篇教程<Java基础教程(4)--面向对象概念>中介绍的那样,对象将它的状态存在域中.但是你可能仍然有一些疑问,例如:命名一个域的规则和惯例是什么?除 ...
随机推荐
- win32之临界区
线程安全问题 每个线程都有自己的栈,而局部变量是存储在栈中的,这就意味着每个线程都有一份自己的"局部变量",如果线程 仅仅使用 "局部变量" 那么就不存在线程安 ...
- Go module 本地导包方式
tip本文只讲关于Go module 本地导包方式,其他请自行查阅 Go module 导包方式,go mod init project-name,会得到一个go.mod文件,此文件是管理依赖的,通常 ...
- 学习写简单Spring源码demo
最近在研究怎么实现简单的Spring的源码,通过注解的方式来实现对bean的加载管理. 首先先来看下我的工程结构: (1)spring-common:定义了常用的枚举常量,工具类(如FileUtils ...
- mysql管理表关系
表关系管理 关注公众号"轻松学编程"了解更多. 1.概述 表与表之间的关系可以是一对一.一对多.多对一的.通过外键把表连接起来,外键放在任意一张表都可以,通常选择由从表(相对次 ...
- GDB调试基础使用方法
尽管目前使用的VS code可以使用插件一键构建和运行程序,但GDB作为调试利器,还是值得花时间去学习的. 概述 GDB(GNU Debugger) 是一个由GNU开源组织发布的.UNIX/LINUX ...
- CF1295E Permutation Separation
线段树 难得把E想出来,写出来,但却没有调出来(再给我5分钟),我的紫名啊,我一场上紫的大好机会啊 首先考虑是否能将$k$在$1$--$n-1$的每一个的最小代价都求出来 因为$k$从$i$到$i-1 ...
- kubernetes-1.18.2集群安装-02
一.基础配置 修改主机名 # 在 172.17.32.23 上:hostnamectl set-hostname k8s-master01bash# 在 172.17.32.38 上:hostnam ...
- CORS跨域请求:前后端分离
1. 请求过滤器: /** * OncePerRequestFilter保证在任何Servlet容器中都是一个请求只执行一次的过滤器. */ public class CorsFilter exten ...
- prometheus监控golang服务实践
一.prometheus基本原理介绍 prometheus是基于metric采样的监控,可以自定义监控指标,如:服务每秒请求数.请求失败数.请求执行时间等,每经过一个时间间隔,数据都会从运行的服务中流 ...
- @AliasFor注解
@AliasFor注解 @AliasFor是一个注解,用于为注解属性声明别名. 代码如下:它有两个属性value和attribute @AliasFor注解注释了 自身,并且value和attribu ...