Java基础知识之注解基本使用教程

Posted smileNicky

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java基础知识之注解基本使用教程相关的知识,希望对你有一定的参考价值。

1、什么是java注解?

定义:注解(Annotation),也称之为元数据。是一种代码级别的说明,是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

作用分类:

  • 1、编写文档:通过代码里标识的注解生成文档
  • 2、代码分析:通过代码里标识的注解对代码进行分析
  • 3、编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查

2、JDK中的注解

JDK中的主键比较多,下面列举一些进行说明

@Override:检查被该注解注释的是否是继承自父类
@Deprecated:表示被注释的内容已经过时,不过还可以用
@SuppressWarnings:压制警告

@SuppressWarnings,压制警告属性:

  • all to suppress all warnings (抑制所有警告)
  • boxing to suppress warnings relative to boxing/unboxing operations(抑制装箱、拆箱
    操作时候的警告)
  • cast to suppress warnings relative to cast operations (抑制映射相关的警告)
  • dep-ann to suppress warnings relative to deprecated annotation(抑制启用注释的警
    告)
  • deprecation to suppress warnings relative to deprecation(抑制过期方法警告)
  • fallthrough to suppress warnings relative to missing breaks in switch
    statements(抑制确在switch中缺失breaks的警告)
  • finally to suppress warnings relative to finally block that don’t return (抑制
    finally模块没有返回的警告)
  • hiding to suppress warnings relative to locals that hide variable()
  • incomplete-switch to suppress warnings relative to missing entries in a switch
    statement (enum case)(忽略没有完整的switch语句)
  • nls to suppress warnings relative to non-nls string literals(忽略非nls格式的字符)
  • null to suppress warnings relative to null analysis(忽略对null的操作)
  • rawtypes to suppress warnings relative to un-specific types when using generics
    on class params(使用generics时忽略没有指定相应的类型)
  • restriction to suppress warnings relative to usage of discouraged or forbidden
    references
  • serial to suppress warnings relative to missing serialVersionUID field for a
    serializable class(忽略在serializable类中没有声明serialVersionUID变量)
  • static-access to suppress warnings relative to incorrect static access(抑制不正
    确的静态访问方式警告)
  • synthetic-access to suppress warnings relative to unoptimized access from inner
    classes(抑制子类没有按最优方法访问内部类的警告)
  • unchecked to suppress warnings relative to unchecked operations(抑制没有进行类型检
    查操作的警告)
  • unqualified-field-access to suppress warnings relative to field access
    unqualified (抑制没有权限访问的域的警告)
  • unused to suppress warnings relative to unused code (抑制没被使用过的代码的警告)

@SuppressWarnings("all")
public class AnnotaionSimpleExample {

    /**
     * 接口过时,注释,不过还是可以使用的
     * @Param []
     * @return void
     */
    @Deprecated
    public void v1() {
    }

    /**
     * 新版接口,推荐用户使用
     * @Param []
     * @return void
     */
    public void v2(){}


    @Override
    public String toString() {
        return super.toString();
    }
}

3、自定义注解

语法:

public @interface [主键类名称] {	}

注解本质,自定义注解被反编译后的内容,所以主键的本质就是实现了java.lang.annotation.Annotation这个父类的接口,所以注解本质就是一个接口

public interface MyAnnotaion extends java.lang.annotation.Annotation {
}

注解注意事项:

  • 方法不应有任何 throws 子句
  • 方法应返回以下:基本数据类型、String类型、枚举类型、注解或者是这些类型的数组
  • 方法不应有任何参数
  • 在 interface 关键字之前附加 @ 来定义注释
  • 可以使用default关键字为该方法分配一个默认值,返回值如果是数组,default后面加上{}
public @interface MyAnnotation {
    int value1() default 1;
    String value2() default "";
    String value3() default "str";
    int[] intarr() default {1,2,3,4,5,6};
    
}

4、元注解

JDK中提供了4个元注解,在自定义注解时候经常需要用到

  • 1、@Target:描述当前注解能够作用的位置
    • ElementType.TYPE:作用在类上
    • ElementType.METHOD:作用在方法上
    • ElementType.FIELD:作用在成员变量上
  • 2、@Retention:描述注解被保留到的阶段
    • SOURCE:表示当前注解只有在代码阶段有效,编译期间丢弃
    • CLASS:该注解会被保留到字节码阶段,指.class文件,提供给java编译器而不是JVM,包含在class文件
    • RUNTIME:该注解会被保留到运行阶段 JVM,指的是运行时,可供 java 编译器和 JVM 使用
    • SOURCE < CLASS < RUNTIME
  • 3、@Documented:描述注解是否被抽取到JavaDoc api
  • 4、@Inherited:描述注解是否可以被子类继承

import java.lang.annotation.*;

@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MyAnnotation {
    int value1() default 1;
}

5、自定义注解案例

下面通过一个例子,加上Spring AOP实现日志打印,加上这个自定义注释的方法都会被拦截,然后获取参数打印日志

自定义注解类:作用于方法


import java.lang.annotation.*;

/**
 * <pre>
 *      日志记录注解类
 * </pre>
 *
 * <pre>
 * @author mazq
 * 修改记录
 *    修改后版本:     修改人:  修改日期: 2021/08/11 09:32  修改内容:
 * </pre>
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface EnableLogger {


}

pom加上spring-boot-starter-web和spring-boot-starter-aop

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
 </dependency>

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-aop</artifactId>
 </dependency>

日志打印Aspect类:


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

/**
 * <pre>
 *      日志打印Aspect类
 * </pre>
 *
 * <pre>
 * @author mazq
 * 修改记录
 *    修改后版本:     修改人:  修改日期: 2021/08/11 09:42  修改内容:
 * </pre>
 */
@Aspect
@Component
@EnableAspectJAutoProxy
public class LoggerAspect {

    private Logger LOG = LoggerFactory.getLogger(LoggerAspect.class);

    @Pointcut("@annotation(com.example.core.example.annotation.EnableLogger)")
    public void pointCutMethod(){}

    @Around("pointCutMethod()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        if (LOG.isInfoEnabled()) {
            LOG.info(
                    "#method: {} ,args: {} , result:{}, used: {} ms",
                    MethodSignature.class.cast(joinPoint.getSignature()).getMethod().getName(),
                    joinPoint.getArgs(),
                    result,
                    System.currentTimeMillis() - start);
        }
        return result;
    }
}

用户信息实体类:


import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;

import java.io.Serializable;

/**
 * <pre>
 *  用户信息实体类
 *
 *
 * <pre>
 * 修改记录
 *    修改后版本:     修改人:  修改日期: 2020/07/20 10:14  修改内容:
 * </pre>
 */
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public class GithubUser implements Serializable {

    private String name;
    private String blog;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\\'' +
                ", blog='" + blog + '\\'' +
                '}';
    }
}

RESTFul API测试:


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * <pre>
 *      测试控制类
 * </pre>
 *
 * <pre>
 * @author mazq
 * 修改记录
 *    修改后版本:     修改人:  修改日期: 2021/08/11 10:03  修改内容:
 * </pre>
 */
@RestController
public class HelloController {

    private Logger LOG = LoggerFactory.getLogger(HelloController.class);

    private final RestTemplate restTemplate;

    public HelloController(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder.build();
    }

    /**
     *  <pre>获取github用户信息 RESTFUL API </pre>
     * {@link ://127.0.0.1:8080/api/hello/mojombo}
     * @Author mazq
     * @Date 2021/08/11 10:11
     * @Param [userCode]
     * @return org.springframework.http.ResponseEntity<?>
     */
    @EnableLogger
    @RequestMapping(value = {"/api/hello/{userCode}"})
    public ResponseEntity<?> hello(@PathVariable("userCode") String userCode) {
        LOG.info("Looking up " + userCode);
        String url = String.format("https://api.github.com/users/%s", userCode);
        GithubUser userInfo = restTemplate.getForObject(url, GithubUser.class);
        return ResponseEntity.ok(userInfo);
    }
}

在linux里调用接口:

curl http://127.0.0.1:8080/api/hello/mojombo

返回json:

{
  "name": "Tom Preston-Werner",
  "blog": "http://tom.preston-werner.com"
}

被Spring AOP拦截,实现日志打印

#method: hello ,args: [mojombo] , result:<200 OK OK,User{name=‘Tom Preston-Werner’, blog=‘http://tom.preston-werner.com’},[]>, used: 1791 ms

以上是关于Java基础知识之注解基本使用教程的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot 系列教程之事务隔离级别知识点小结

Java基础之方法的调用重载以及简单的递归

Java注解知识点摘抄

java注解的基本知识

Java基础教程(16)--注解

Mybatis 教程之Mybatis注解开发