本文目录导读:

我将为您展示一个完整的自定义注解实现案例,包括注解定义、处理器实现以及实际应用。
自定义注解定义
import java.lang.annotation.*;
// 1. 日志注解
@Target(ElementType.METHOD) // 只能用在方法上
@Retention(RetentionPolicy.RUNTIME) // 运行时保留
@Documented // 生成文档
public @interface LogAnnotation {
// 操作类型
String action() default "";
// 操作描述
String description() default "";
// 是否记录参数
boolean recordParams() default true;
// 日志级别
LogLevel level() default LogLevel.INFO;
enum LogLevel {
INFO, WARN, ERROR
}
}
import java.lang.annotation.*;
// 2. 参数校验注解
@Target(ElementType.FIELD) // 用在字段上
@Retention(RetentionPolicy.RUNTIME)
public @interface Validate {
// 是否必填
boolean required() default true;
// 最小长度
int minLength() default 0;
// 最大长度
int maxLength() default Integer.MAX_VALUE;
// 正则表达式
String pattern() default "";
// 错误消息
String message() default "参数校验失败";
}
import java.lang.annotation.*;
// 3. 缓存注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Cacheable {
// 缓存key
String key() default "";
// 过期时间(秒)
int expire() default 60;
// 是否缓存空值
boolean cacheNull() default false;
}
注解处理器实现
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.Date;
@Aspect
@Component
public class LogAspect {
private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);
@Around("@annotation(logAnnotation)")
public Object around(ProceedingJoinPoint joinPoint, LogAnnotation logAnnotation) throws Throwable {
// 获取方法签名
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String methodName = signature.getMethod().getName();
String className = joinPoint.getTarget().getClass().getSimpleName();
// 开始时间
long startTime = System.currentTimeMillis();
// 构建日志信息
StringBuilder logInfo = new StringBuilder();
logInfo.append("\n========== 开始执行 ==========\n");
logInfo.append("操作类名: ").append(className).append("\n");
logInfo.append("操作方法: ").append(methodName).append("\n");
logInfo.append("操作类型: ").append(logAnnotation.action()).append("\n");
logInfo.append("操作描述: ").append(logAnnotation.description()).append("\n");
// 记录参数
if (logAnnotation.recordParams()) {
Object[] args = joinPoint.getArgs();
logInfo.append("方法参数: ").append(Arrays.toString(args)).append("\n");
}
Object result = null;
try {
// 执行原方法
result = joinPoint.proceed();
// 记录执行结果
logInfo.append("执行结果: SUCCESS\n");
logInfo.append("返回结果: ").append(result).append("\n");
// 根据日志级别输出
switch (logAnnotation.level()) {
case ERROR:
logger.error(logInfo.toString());
break;
case WARN:
logger.warn(logInfo.toString());
break;
default:
logger.info(logInfo.toString());
}
} catch (Exception e) {
logInfo.append("执行结果: FAIL\n");
logInfo.append("异常信息: ").append(e.getMessage()).append("\n");
logger.error(logInfo.toString());
throw e;
} finally {
long endTime = System.currentTimeMillis();
logger.info("执行耗时: {} ms", endTime - startTime);
logger.info("========== 结束执行 ==========");
}
return result;
}
}
参数校验处理器
import java.lang.reflect.Field;
import java.util.regex.Pattern;
public class ValidationProcessor {
/**
* 校验对象
*/
public static void validate(Object obj) throws IllegalAccessException, ValidationException {
if (obj == null) {
throw new ValidationException("对象不能为空");
}
Class<?> clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// 设置字段可访问
field.setAccessible(true);
// 检查是否有Validate注解
Validate annotation = field.getAnnotation(Validate.class);
if (annotation == null) {
continue;
}
Object value = field.get(obj);
// 校验必填
if (annotation.required() && value == null) {
throw new ValidationException(
String.format("%s不能为空: %s", field.getName(), annotation.message())
);
}
if (value != null) {
// 校验长度
if (value instanceof String) {
String strValue = (String) value;
// 校验最小长度
if (strValue.length() < annotation.minLength()) {
throw new ValidationException(
String.format("%s长度最小为%d: %s",
field.getName(), annotation.minLength(), annotation.message())
);
}
// 校验最大长度
if (strValue.length() > annotation.maxLength()) {
throw new ValidationException(
String.format("%s长度最大为%d: %s",
field.getName(), annotation.maxLength(), annotation.message())
);
}
// 正则校验
if (!annotation.pattern().isEmpty()) {
Pattern pattern = Pattern.compile(annotation.pattern());
if (!pattern.matcher(strValue).matches()) {
throw new ValidationException(
String.format("%s格式不正确: %s", field.getName(), annotation.message())
);
}
}
}
}
}
}
// 自定义校验异常
public static class ValidationException extends RuntimeException {
public ValidationException(String message) {
super(message);
}
}
}
缓存处理器
import org.springframework.stereotype.Component;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class CacheProcessor {
// 简单的本地缓存
private static ConcurrentHashMap<String, CacheEntry> cache = new ConcurrentHashMap<>();
/**
* 缓存条目
*/
private static class CacheEntry {
Object value;
long expireTime;
public CacheEntry(Object value, long expireTime) {
this.value = value;
this.expireTime = expireTime;
}
public boolean isExpired() {
return System.currentTimeMillis() > expireTime;
}
}
/**
* 从缓存获取数据
*/
public static Object get(String key) {
CacheEntry entry = cache.get(key);
if (entry != null) {
if (!entry.isExpired()) {
return entry.value;
} else {
cache.remove(key);
}
}
return null;
}
/**
* 放入缓存
*/
public static void put(String key, Object value, int expireSeconds) {
long expireTime = System.currentTimeMillis() + expireSeconds * 1000;
cache.put(key, new CacheEntry(value, expireTime));
}
/**
* 清除缓存
*/
public static void clear() {
cache.clear();
}
/**
* 获取cache size
*/
public static int size() {
return cache.size();
}
}
使用示例
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class UserService {
/**
* 注册用户 - 使用日志注解
*/
@LogAnnotation(
action = "用户注册",
description = "注册新用户",
level = LogAnnotation.LogLevel.INFO
)
public Map<String, Object> registerUser(@Validate User user) throws Exception {
// 手动校验(也可以通过AOP自动校验)
ValidationProcessor.validate(user);
Map<String, Object> result = new HashMap<>();
result.put("success", true);
result.put("userId", System.currentTimeMillis());
result.put("username", user.getUsername());
return result;
}
/**
* 获取用户信息 - 使用缓存注解
*/
@Cacheable(key = "#userId", expire = 30)
public Map<String, Object> getUserById(Long userId) {
// 模拟查询数据库
Map<String, Object> user = new HashMap<>();
user.put("id", userId);
user.put("name", "用户" + userId);
user.put("email", "user" + userId + "@example.com");
return user;
}
/**
* 更新用户 - 使用日志注解
*/
@LogAnnotation(
action = "更新用户",
description = "更新用户信息",
level = LogAnnotation.LogLevel.WARN
)
public void updateUser(Long userId, String email) {
System.out.println("更新用户: " + userId + ", email: " + email);
// 实际更新逻辑
}
}
配合AOP自动校验
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class ValidationAspect {
/**
* 自动校验带有@Validate注解的参数
*/
@Around("execution(* *(.., @Validate (*), ..))")
public Object validateParams(ProceedingJoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs();
// 校验所有包含Validate注解的参数
for (Object arg : args) {
if (arg != null) {
try {
ValidationProcessor.validate(arg);
} catch (ValidationProcessor.ValidationException e) {
throw new RuntimeException("参数校验失败: " + e.getMessage());
}
}
}
return joinPoint.proceed();
}
}
综合使用示例
import java.util.Map;
public class AnnotationExample {
public static void main(String[] args) throws Exception {
UserService userService = new UserService();
// 创建用户对象
User user = new User();
user.setUsername("test_user");
user.setEmail("test@example.com");
user.setPassword("123456");
// 注册用户
Map<String, Object> result = userService.registerUser(user);
System.out.println("注册结果: " + result);
// 获取用户(带缓存)
Map<String, Object> userInfo = userService.getUserById(1L);
System.out.println("用户信息: " + userInfo);
// 再次获取(命中缓存)
Map<String, Object> cachedUser = userService.getUserById(1L);
System.out.println("缓存用户信息: " + cachedUser);
// 更新用户
userService.updateUser(1L, "newemail@example.com");
}
}
实体类定义
public class User {
@Validate(required = true, minLength = 3, maxLength = 20,
message = "用户名长度必须在3-20个字符之间")
private String username;
@Validate(required = true, pattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
message = "邮箱格式不正确")
private String email;
@Validate(required = true, minLength = 6, maxLength = 20,
message = "密码长度必须在6-20个字符之间")
private String password;
// getter和setter
}
运行结果示例
========== 开始执行 ==========
操作类名: UserService
操作方法: registerUser
操作类型: 用户注册
操作描述: 注册新用户
方法参数: [User{username='test_user', email='test@example.com', password='123456'}]
执行结果: SUCCESS
返回结果: {success=true, userId=1234567890, username=test_user}
执行耗时: 12 ms
========== 结束执行 ==========
注册结果: {success=true, userId=1234567890, username=test_user}
用户信息: {id=1, name=用户1, email=user1@example.com}
缓存用户信息: {id=1, name=用户1, email=user1@example.com}
这个案例展示了自定义注解的完整实现:
- 注解定义:定义日志、校验、缓存三种注解
- 处理器实现:通过AOP实现日志记录和参数校验
- 实际应用:在业务类中应用注解
- 扩展能力:支持自定义属性、默认值、枚举类型等
这种设计模式可以大大提高代码的复用性和维护性,是实现AOP编程的重要方式。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播