java中实现自定义注解
使用@interface// 自定义注解:标记需要日志记录的方法@Target(ElementType.METHOD) // 仅作用于方法@Retention(RetentionPolicy.RUNTIME) // 运行时保留,可反射解析@Documented // 生成Javadoc时包含该注解// 注解属性(类似接口方法,可指定默认值)String value() default "操作日志"
·
一. 注解的基本概念
- 注解(Annotation) 是 Java 1.5 引入的特性,用于为代码提供元数据(描述数据的数据)。
- 自定义注解需使用
@interface关键字定义,本质是一种特殊的接口。 - 需通过元注解(描述注解的注解)指定自定义注解的行为(如作用范围、保留周期等)。
二. 常用元注解
定义自定义注解时,通常需要添加以下元注解:
@Target:指定注解可作用的位置(如类、方法、字段等),取值来自ElementType枚举:TYPE(类 / 接口)、METHOD(方法)、FIELD(字段)、PARAMETER(参数)等。
@Retention:指定注解的保留周期,取值来自RetentionPolicy枚举:SOURCE:仅在源码中保留(如@Override)。CLASS:保留到字节码(默认,类加载时会被丢弃)。RUNTIME:保留到运行时(可通过反射解析,最常用)。
@Documented:指定注解是否在 Javadoc 中显示。@Inherited:指定注解是否可被子类继承。
三.自定义注解的实现步骤
1.定义自定义注解
使用 @interface 关键字定义注解,并结合元注解指定行为:
import java.lang.annotation.*;
// 自定义注解:标记需要日志记录的方法
@Target(ElementType.METHOD) // 仅作用于方法
@Retention(RetentionPolicy.RUNTIME) // 运行时保留,可反射解析
@Documented // 生成Javadoc时包含该注解
public @interface Log {
// 注解属性(类似接口方法,可指定默认值)
String value() default "操作日志"; // 日志描述
boolean needLogParams() default true; // 是否记录参数
}
- 注解属性的定义格式:
类型 属性名() [default 默认值]。 - 如果属性名是
value,使用时可省略属性名(如@Log("保存用户"))。
2.使用注解
在目标方法上添加自定义注解:
public class UserService {
// 使用自定义注解,指定日志描述
@Log(value = "添加用户", needLogParams = true)
public void addUser(String username, int age) {
System.out.println("执行添加用户:" + username);
}
// 使用默认值
@Log
public void deleteUser(int id) {
System.out.println("执行删除用户:" + id);
}
}
3.解析注解
通过反射获取注解信息并处理:
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class LogAnnotationProcessor {
public static void process(Object service) throws Exception {
// 获取类的Class对象
Class<?> clazz = service.getClass();
// 获取所有方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
// 判断方法是否被@Log注解标记
if (method.isAnnotationPresent(Log.class)) {
// 获取注解实例
Log logAnnotation = method.getAnnotation(Log.class);
// 解析注解属性
String logDesc = logAnnotation.value();
boolean needParams = logAnnotation.needLogParams();
// 模拟日志记录逻辑
System.out.println("\n===== 日志开始 =====");
System.out.println("操作描述:" + logDesc);
// 如果需要记录参数
if (needParams) {
Parameter[] parameters = method.getParameters();
System.out.print("参数列表:");
for (Parameter param : parameters) {
System.out.print(param.getName() + "(" + param.getType().getSimpleName() + "), ");
}
}
System.out.println("\n===== 日志结束 =====");
}
}
}
public static void main(String[] args) throws Exception {
// 测试:解析UserService中的@Log注解
UserService userService = new UserService();
process(userService);
}
}
四、注意事项
- 注解属性的类型只能是:基本类型、String、Class、枚举、注解或以上类型的数组。
- 如果注解没有属性,称为 “标记注解”(如
@Override,标记该方法为重写)。 - 解析注解时,需确保
@Retention为RUNTIME,否则反射无法获取。 - 实际开发中,注解解析常结合 AOP(如 Spring AOP)实现无侵入式功能(如日志、权限校验)。
应用场景
- 框架集成:Spring 的
@Transactional、MyBatis 的@Select等均基于自定义注解。 - 代码简化:通过注解替代 XML 配置,提升可读性。
- 运行时检查:如参数校验(
@NotNull)、自动化测试等。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)