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基础知识之注解基本使用教程的主要内容,如果未能解决你的问题,请参考以下文章