栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java(十四)注解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java(十四)注解

文章目录

注解以及自定义注解的使用

注解入门

什么是注解?注解的作用:内置注解meta-annotation(元注解)

@Target注解@Retention注解@Inherited注解@documented注解 自定义注解

应用场景一:自定义注解+拦截器 实现登录校验应用场景二:自定义注解+AOP 实现日志打印

注解以及自定义注解的使用 注解入门 什么是注解?

注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便地使用这些数据。注解类型定义指定了一种新的类型,一种特殊的接口类型。 在关键词 interface 前加 @ 符号也就是用 @interface 来区分注解的定义和普通的接口声明。目前大部分框架(如 Spring Boot 等)都通过使用注解简化了代码并提高的编码效率。

注解的作用:

提供信息给编译器: 编译器可以利用注解来探测错误和警告信息,如 @Override、@Deprecated。编译阶段时的处理: 软件工具可以用来利用注解信息来生成代码、Html 文档或者做其它相应处理,如 @Param、@Return、@See、@Author 用于生成 Javadoc 文档。运行时的处理: 某些注解可以在程序运行的时候接受代码的提取,值得注意的是,注解不是代码本身的一部分。如Spring 2.5 开始注解配置,减少了配置。 内置注解

@Override

@SuppressWarnings()

meta-annotation(元注解)

除了直接使用JDK 定义好的注解,我们还可以自定义注解,在JDK 1.5中提供了4个标准的用来对注解类型进行注解的注解类,我们称之为 meta-annotation(元注解),他们分别是:

@Target

@Retention

@documented

@Inherited

@Target注解

Target注解的作用是:描述注解的使用范围(即:被修饰的注解可以用在什么地方) 。

Target注解用来说明那些被它所注解的注解类可修饰的对象范围:注解可以用于修饰 packages、types(类、接口、枚举、注解类)、类成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数),在定义注解类时使用了@Target 能够更加清晰的知道它能够被用来修饰哪些对象,它的取值范围定义在ElementType 枚举中。

public enum ElementType {
 
    TYPE, // 类、接口、枚举类
 
    FIELD, // 成员变量(包括:枚举常量)
 
    METHOD, // 成员方法
 
    PARAMETER, // 方法参数
 
    CONSTRUCTOR, // 构造方法
 
    LOCAL_VARIABLE, // 局部变量
 
    ANNOTATION_TYPE, // 注解类
 
    PACKAGE, // 可用于修饰:包
 
    TYPE_PARAMETER, // 类型参数,JDK 1.8 新增
 
    TYPE_USE // 使用类型的任何地方,JDK 1.8 新增
 
}
@Retention注解

Reteniton注解的作用是:表示注解在什么时候有用(即:被描述的注解在它所修饰的类中可以被保留到何时) 。

Reteniton注解用来限定那些被它所注解的注解类在注解到其他类上以后,可被保留到何时,一共有三种策略,定义在RetentionPolicy枚举中。

public enum RetentionPolicy {
 // RUNTIME>CLASS>SOURCE
    SOURCE,    // 源文件保留
    CLASS,       // 编译期保留,默认值
    RUNTIME   // 运行期保留,可通过反射去获取注解信息
}
@Inherited注解

Inherited注解的作用是:使被它修饰的注解具有继承性(如果某个类使用了被@Inherited修饰的注解,则其子类将自动具有该注解)。

@documented注解

documented注解的作用是:描述在使用 javadoc 工具为类生成帮助文档时是否要保留其注解信息。

自定义注解

1.添加元注解

2.是否设置参数、默认值,如果只有一个,设置为value,赋值时可以不写

public class test01 {
    //注解可以显示赋值,如果没有默认值,需要给注解赋值
    @MYAno(name = "xiaohua")
    public void t() {

    }
}

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MYAno {
    //注解的参数:参数类型+参数名(;
    String name() default "";
}

通过反射机制可以实现对元数据的访问

应用场景一:自定义注解+拦截器 实现登录校验

接下来,我们使用springboot拦截器实现这样一个功能,如果方法上加了@LoginRequired,则提示用户该接口需要登录才能访问,否则不需要登录。

首先定义一个LoginRequired注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {  }

然后写两个简单的接口,访问sourceA,sourceB资源

@RestController
public class IndexController {
 
    @GetMapping("/sourceA")
    public String sourceA(){
        return "你正在访问sourceA资源";
    }
 
    @GetMapping("/sourceB")
    public String sourceB(){
        return "你正在访问sourceB资源";
    }
 
}

实现spring的HandlerInterceptor 类先实现拦截器,但不拦截,只是简单打印日志,如下:

public class SourceAccessInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("进入拦截器了");
        return true;
    }
 
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
 
    }
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
 
    }
}

实现spring类WebMvcConfigurer,创建配置类把拦截器添加到拦截器链中

@Configuration
public class InterceptorTrainConfigurer implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SourceAccessInterceptor()).addPathPatterns("
@Aspect // 1.表明这是一个切面类
@Component
public class MyLogAspect {

    // 2. PointCut表示这是一个切点,@annotation表示这个切点切到一个注解上,后面带该注解的全类名
    // 切面最主要的就是切点,所有的故事都围绕切点发生
    // logPointCut()代表切点名称
    @Pointcut("@annotation(com.watson.traffic.blog.trafficblog.config.MyLog)")
    public void logPointCut() {
    }

    // 3. 环绕通知
    @Around("logPointCut()")
    public void logAround(ProceedingJoinPoint joinPoint) {
        // 获取方法名称
        String methodName = joinPoint.getSignature().getName();
        // 获取入参
        Object[] param = joinPoint.getArgs();

        StringBuilder sb = new StringBuilder();
        for (Object o : param) {
            sb.append(o + "; ");
        }
        System.out.println("进入[" + methodName + "]方法,参数为:" + sb.toString());

        // 继续执行方法
        try {
            joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println(methodName + "方法执行结束");

    }
}

在步骤二中的IndexController写一个sourceC进行测试,加上我们的自定义注解:

    @MyLog
    @GetMapping("/sourceC/{source_name}")
    public String sourceC(@PathVariable("source_name") String sourceName){
        return "你正在访问sourceC资源";
    }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/770557.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号