自定义注解实现案例

wen java案例 2

本文目录导读:

自定义注解实现案例

  1. 自定义注解定义
  2. 注解处理器实现
  3. 参数校验处理器
  4. 缓存处理器
  5. 使用示例
  6. 配合AOP自动校验
  7. 综合使用示例
  8. 实体类定义
  9. 运行结果示例

我将为您展示一个完整的自定义注解实现案例,包括注解定义、处理器实现以及实际应用。

自定义注解定义

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}

这个案例展示了自定义注解的完整实现:

  1. 注解定义:定义日志、校验、缓存三种注解
  2. 处理器实现:通过AOP实现日志记录和参数校验
  3. 实际应用:在业务类中应用注解
  4. 扩展能力:支持自定义属性、默认值、枚举类型等

这种设计模式可以大大提高代码的复用性和维护性,是实现AOP编程的重要方式。

抱歉,评论功能暂时关闭!