注解的使用案例

注解的使用案例有很多,比如:

  • 使用注解来生成文档,如javadoc中的@author,@param等。
  • 使用注解来跟踪代码依赖性,实现替代配置文件功能,如spring mvc中的@Controller,@RequestMapping等。
  • 使用注解来编译时进行格式检查,如@Override,@Deprecated等。
  • 使用注解来编译时进行代码生成补全,如lombok插件中的@Data,@Getter等。
  • 使用注解来运行时进行反射操作,如Hibernate中的@Entity,@Column等。

下面是一些具体的案例123

  • 使用自定义注解和拦截器实现登录校验。首先定义一个名为LoginRequired的注解,用来标记需要登录才能访问的方法。然后定义一个拦截器类,实现HandlerInterceptor接口,在preHandle方法中判断请求方法是否有LoginRequired注解,如果有则检查用户是否已经登录,如果没有则跳转到登录页面或返回错误信息。最后在spring mvc的配置文件中注册拦截器,并指定拦截路径。
// 定义一个名为LoginRequired的注解
@Target(ElementType.METHOD) // 作用于方法上
@Retention(RetentionPolicy.RUNTIME) // 运行时有效
public @interface LoginRequired {
    // 定义一个布尔值参数,表示是否需要登录,默认为true
    boolean value() default true;
}

// 定义一个拦截器类
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 判断handler是否是处理器方法
        if (handler instanceof HandlerMethod) {
            // 强制转换为HandlerMethod对象
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            // 获取方法上的LoginRequired注解
            LoginRequired loginRequired = handlerMethod.getMethodAnnotation(LoginRequired.class);
            // 如果注解不为空且value为true,则表示需要登录
            if (loginRequired != null && loginRequired.value()) {
                // 获取session中的用户信息
                User user = (User) request.getSession().getAttribute("user");
                // 如果用户为空,则表示未登录
                if (user == null) {
                    // 返回错误信息或跳转到登录页面
                    response.sendRedirect("/login");
                    return false;
                }
            }
        }
        return true;
    }
}

// 在spring mvc的配置文件中注册拦截器,并指定拦截路径
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.example.LoginInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>
  • 使用自定义注解和AOP实现日志打印。首先定义一个名为Loggable的注解,用来标记需要打印日志的方法。然后定义一个切面类,使用@Aspect和@Component注解修饰,并使用@Before和@AfterReturning等通知注解来实现在目标方法执行前后打印日志的功能。最后在spring boot的配置类中开启AOP功能。
// 定义一个名为Loggable的注解
@Target(ElementType.METHOD) // 作用于方法上
@Retention(RetentionPolicy.RUNTIME) // 运行时有效
public @interface Loggable {
    // 定义一个字符串参数,表示日志的级别,默认为info
    String level() default "info";
}

// 定义一个切面类
@Aspect // 表示这是一个切面类
@Component // 表示这是一个组件类,交给spring管理
public class LogAspect {
    // 定义一个日志对象
    private Logger logger = LoggerFactory.getLogger(LogAspect.class);

    // 定义一个切点表达式,表示匹配有Loggable注解的方法
    @Pointcut("@annotation(com.example.Loggable)")
    public void logPointcut() {}

    // 定义一个前置通知,表示在目标方法执行前打印日志
    @Before("logPointcut() && @annotation(loggable)")
    public void beforeLog(JoinPoint joinPoint, Loggable loggable) {
        // 获取方法签名
        Signature signature = joinPoint.getSignature();
        // 获取方法名
        String methodName = signature.getName();
        // 获取日志级别
        String level = loggable.level();
        // 根据日志级别打印不同的日志信息
        switch (level) {
            case "info":
                logger.info("开始执行方法:" + methodName);
                break;
            case "debug":
                logger.debug("开始执行方法:" + methodName);
                break;
            case "error":
                logger.error("开始执行方法:" + methodName);
                break;
            default:
                logger.info("开始执行方法:" + methodName);
        }
    }

    // 定义一个后置通知,表示在目标方法返回后打印日志
    @AfterReturning(pointcut = "logPointcut() && @annotation(loggable)", returning = "result")
    public void afterLog(JoinPoint joinPoint, Loggable loggable, Object result) {
        // 获取方法签名
        Signature signature = joinPoint.getSignature();
        // 获取方法名
        String methodName = signature.getName();
        // 获取日志级别
        String level = loggable.level();
        // 根据日志级别打印不同的日志信息
        switch (level) {
            case "info":
                logger.info("结束执行方法:" + methodName + ",返回结果:" + result);
                break;
            case "debug":
                logger.debug("结束执行方法:" + methodName + ",返回结果:" + result);
                break;
            case "error":
                logger.error("结束执行方法:" + methodName + ",返回结果:" + result);
                break;
            default:
                logger.info("结束执行方法:" + methodName + ",返回结果:" + result);
        }
    }
}

// 在spring boot的配置类中开启AOP功能
@Configuration // 表示这是一个配置类
@EnableAspectJAutoProxy // 表示开启AOP功能
public class AopConfig {
}

为什么后面的功能中不适用getMethodAnnotation获取注解信息?

如果你指的是使用AOP的案例中,为什么不使用getMethodAnnotation获取注解信息,而是使用@annotation(loggable)这样的表达式,那么原因是这样的:

  • 使用getMethodAnnotation需要先获取目标方法的Method对象,然后才能调用该方法获取注解信息。这样做的缺点是需要手动编写反射代码,而且可能会抛出异常。
  • 使用@annotation(loggable)这样的表达式,可以直接将目标方法上的注解对象作为参数传递给通知方法,无需编写反射代码,也不会抛出异常。这样做的优点是更简洁、更安全、更高效。

那么@annotation(loggable)这样的表达式是怎么工作的呢?

@annotation表达式是一种切点表达式,用来匹配目标方法上有指定注解的连接点。1234 例如:

  • @annotation(com.example.Loggable) 表示匹配有Loggable注解的方法。
  • @annotation(appendAnnotation) && args(val) 表示匹配有appendAnnotation注解的方法,并且将注解对象和方法参数传递给通知方法。

@annotation表达式的作用是可以方便地使用自定义注解来标记需要切入的方法,而不需要写复杂的execution表达式。这样可以提高代码的可读性和可维护性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值