java注解详情及自定义注解和使用场景

注解概念

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

jdk预定义的注解

@Override:检查被该注解标注的方式是否是继承自父类【接口】
@Deprecated: 该注解表示注释的内容过时
@SuppressWarnings: 压制警告

jdk提供了4个元注解

JDK中给我们提供的4个元注解

1.@Target:描述当前注解能够作用的位置

ElementType.TYPE:可以作用在类上
ElementType.METHOD:可以作用在方法上
ElementType.FIELD:可以作用在成员变量上

2.@Retention: 描述注解被保留到的阶段

SOURCE < CLASS < RUNTIME
SOURCE:表示当前注解只在代码阶段有效
CLASS:表示该注解会被保留到字节码阶段
RUNTIME:表示该注解会被保留到运行阶段 JVM
自定义的注解:RetentionPolicy.RUNTIME

3.@Documented:描述注解是否被抽取到JavaDoc api中

4.@inherited:描述注解是否可以被子类继承

自定义注解

注解的样式

// 元注解
public @interface 注解名称{
// 属性列表
}

注解的本质

在对该注解类的class文件进行反编译时,发现注解的本质是接口,并继承java.lang.annotation.Annotation
在这里插入图片描述

自定义注解

了解本质后,我们来进行自定义注解的讲解

自定义注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface InvokAnno {
String className();
String methodName();
}

定义studnet1类

public class Student1 {
public void show(){
System.out.println(“student1 show …”);
}
}

测试

@InvokAnno(className = “com.gupao.edu.anno2.Student2”,methodName = “show”)
public class MyMain {
public static void main(String[] args) throws Exception {
// 获取类对象
Class clazz = MyMain.class;
// 获取类对象中的注解
InvokAnno an = clazz.getAnnotation(InvokAnno.class);
/**

  • 注解本质是 接口 获取到的其实是接口的实现
  • public class MyInvokAnno implements InvokAnno{
  • String className(){
  • return “com.gupao.edu.anno2.Student1”;
  • }
  • String methodName(){
  • return “show”;
  • }
  • }
    */
    // 获取注解中对应的属性
    String className = an.className();
    String methodName = an.methodName();
    System.out.println(className);
    System.out.println(methodName);

// 通过反射的方式实现接口的功能
Class<?> aClass = Class.forName(className);
Method show = aClass.getDeclaredMethod(“show”);
// 方法的执行
Object o = aClass.newInstance();
show.invoke(o); // 执行对应的方法
}
}

注解应用场景

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

1.手写注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginAnnotaion {
}

2.拦截器
@Configuration
public class WebMvcConfigurerTest implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new TestInterceptor()).addPathPatterns("/").excludePathPatterns("/js/","/css/","/images/");
}
}

public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(“拦截了”);
HandlerMethod handlerMethod=(HandlerMethod)handler;
//获取拦截的方法
LoginAnnotaion loginAnnotaion=handlerMethod.getMethod().getAnnotation(LoginAnnotaion.class);
//该方法有这个注解,放行,不拦截
if(loginAnnotaion!=null){
return true;
}
response.setContentType(“application/json; charset=utf-8”);
response.getWriter().print(“你访问的资源需要先登录”);
return false;
}

@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 {

}
}

3.controller
@RestController
public class TestController {

//放开
@LoginAnnotaion
@GetMapping("/way/{id}")
public String way(@PathVariable(“id”) Integer id){
return id.toString()+“way”;
}

@GetMapping("/way2/{id}")
public String way2(@PathVariable(“id”) Integer id){
return id.toString()+“way2”;
}
}

场景二:自定义注解+AOP 实现接口执行时间打印

先导入切面和lombok需要的依赖包

org.springframework.boot
spring-boot-starter-aop


org.projectlombok
lombok
true

定义一个注解
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AopAnnotation {
}

写一个aop
@Aspect
@Component
@Slf4j
public class LogAspect {

@Pointcut(value = “@within(com.example.loginrequireannotation.annotation.AopAnnotation) || @annotation(com.example.loginrequireannotation.annotation.AopAnnotation)”)
public void logPointCut(){
}

// 3. 环绕通知

3.controller
@AopAnnotation
@RestController
public class AopController {

@LoginAnnotaion
@GetMapping("/user/{id}")
public String way(@PathVariable(“id”) Integer id){
return id.toString()+“user”;
}

@Around(value = "logPointCut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
    
    
log.info("====== 开始执行 {}.{} ======",
joinPoint.getTarget().getClass(),
joinPoint.getSignature().getName());
// 记录开始时间
long begin = System.currentTimeMillis();

// 执行目标 service
Object result = joinPoint.proceed();

// 记录结束时间
long end = System.currentTimeMillis();
long takeTime = end - begin;
if (takeTime > 3000) {
    
    
log.error("====== 执行结束,耗时:{} 毫秒 ======", takeTime);
} else if (takeTime > 2000) {
    
    
log.warn("====== 执行结束,耗时:{} 毫秒 ======", takeTime);
} else {
    
    
log.info("====== 执行结束,耗时:{} 毫秒 ======", takeTime);
}
return result;
}
}

@LoginAnnotaion
@GetMapping("/teacher/{id}")
public String way2(@PathVariable(“id”) Integer id){
return id.toString()+“teacher”;
}
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42371621/article/details/109056678