文章目录

  • 0.前言
  • 1.创建注解类
  • 1.1.@Target(ElementType.XXX)
  • 1.2.@Retention(RetentionPolicy)
  • 1.3.@interface注解类
  • 1.4.自定义参数
  • 1.5.代码
  • 2.创建切面类
  • 2.1.@annotation(xxx)
  • 2.2.代码
  • 3.在对应的方法上加上注解
  • 4.测试结果
  • 5.进阶内容:代码计时器
  • 5.1.注解类Timing
  • 5.2.切面类TimingAspect
  • 5.3.控制器StudentController
  • 5.4.测试类AopLearningApplicationTests
  • 5.5.测试结果


0.前言

项目:Learning.aop-learning[aop]

1.创建注解类

创建annotation包,在annotation包下创建注解类,类名就是注解名字

自定义注解 java 自定义注解实现_后端

1.1.@Target(ElementType.XXX)

用于声明你自定义的这个注解(@Eshang)可能出现在java程序中的语法位置

  • TYPE:类、接口、注解类上
  • METHOD:方法上
  • FIELD:字段上
  • PARAMETER:参数声明
  • CONSTRUCTOR:构造器声明
  • LOCAL_VARIABLE:局部变量声明
  • ANNOTATION_TYPE:注解类声明(这里只有注解类,普通类不行)
  • PACKAGE:包声明

前四个是最常用,也是最常见的。

如果允许在多个地方出现,则该内容可以用大括号将其括起,

如@Target({ElementType.METHOD, ElementType.Type}) 表示注解能出现在类或方法上

1.2.@Retention(RetentionPolicy)

用于声明注解在何时有效

  • RUNTIME:运行时有效
  • CLASS:注解将被编译器在类文件中记录,但在运行时不需要JVM保留
  • SOURCE:注解只在源代码保留,编译时将被忽略

同样的,如果允许多个地方出现,则可以用大括号将其括起。

1.3.@interface注解类

声明这是一个注解类。

1.4.自定义参数

使用注解时,可以在括号中对一些参数进行赋值

而这些参数最初便在这里定义。格式为:

//类型 参数名 default 默认值;
String value() default "Eshang";

若括号中没有写,则采用defaut后的默认值

1.5.代码

package com.eshang.aop.learning.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author xyx-Eshang
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Eshang {
   String value() default "Eshang";

   boolean admin() default false;
}

2.创建切面类


自定义注解 java 自定义注解实现_java_02

2.1.@annotation(xxx)

在@Around()的括号中写"@annotation(xxx)"

@Around("@annotation(eshang)")
public Object eshangAdvice(ProceedingJoinPoint pjp, Eshang eshang) throws Throwable{
    ...
}

里层括号分为两种情况:

  • 未在形参中定义:写注解类的全限定名,此处为:
    com.eshang.aop.learning.annotation.Eshang
  • 已在形参中定义:写形参

当然,也可以再连接execution(xxx)表达式,如

自定义注解 java 自定义注解实现_后端_03

2.2.代码

package com.eshang.aop.learning.annotation;

import com.eshang.aop.learning.annotation.Eshang;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 * @author xyx-Eshang
 */
@Aspect
@Component
public class EshangAspect {
   @Around("@annotation(eshang)")
   public Object eshangAdvice(ProceedingJoinPoint pjp, Eshang eshang) throws Throwable {
      try {
         System.out.println("自定义注解已被实现!");
         Object result = pjp.proceed();
         System.out.println("获取value为:" + eshang.value());
         System.out.println("获取admin为:" + eshang.admin());
         return result;
      } catch (Exception e) {
         System.out.println("发生异常,请重新检查代码!");
         return null;
      }
   }
}

3.在对应的方法上加上注解

自定义注解 java 自定义注解实现_spring boot_04

package com.eshang.aop.learning.controller;

import com.eshang.aop.learning.annotation.Eshang;
import com.eshang.aop.learning.annotation.Timing;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author xyx-Eshang
 */
@RestController
@RequestMapping("/student")
public class StudentController {

   @Eshang(value = "LaLaLa")
   @PostMapping("/testAop")
   public void testAop() {
      System.out.println("现在执行testAop方法");
   }
}

4.测试结果

自定义注解 java 自定义注解实现_后端_05

package com.eshang.aop.learning;

import com.eshang.aop.learning.controller.StudentController;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

@SpringBootTest
class AopLearningApplicationTests {
   @Resource
   StudentController studentController;

   @Test
   void contextLoads() {
      studentController.testAop();
   }

}

5.进阶内容:代码计时器

目标:用注解的形式实现代码计时器,对代码运行时间计时,并且可以在注解中自行定义计时单位

5.1.注解类Timing

自定义注解 java 自定义注解实现_java_06

package com.eshang.aop.learning.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author xyx-Eshang
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Timing {
   String unit() default "ms";
}

5.2.切面类TimingAspect

自定义注解 java 自定义注解实现_自定义注解 java_07

package com.eshang.aop.learning.annotation;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 * @author xyx-Eshang
 */
@Aspect
@Component
public class TimingAspect {
   @Around("@annotation(timing)")
   public Object timingAdvice(ProceedingJoinPoint pjp, Timing timing) throws Throwable {
      try {
         double beforeTime = System.currentTimeMillis();
         Object result = pjp.proceed();
         double consuming = System.currentTimeMillis() - beforeTime;
         //根据单位,对显示的数值进行处理
         if ("s".contentEquals(timing.unit())) {
            consuming = consuming / 1000;
         } else if("min".contentEquals(timing.unit())){
            consuming = consuming / (1000 * 60);
         } else if ("h".contentEquals(timing.unit())) {
            consuming = consuming / (1000 * 60 * 60);
         }
         System.out.println("总用时为:" + consuming + timing.unit());
         return result;
      } catch (Exception e) {
         System.out.println("发生异常,请检查AOP的代码!");
         return null;
      }
   }
}

5.3.控制器StudentController

在testAop方法上使用@Timing(unit = “s”),括号内容表示以秒为单位

package com.eshang.aop.learning.controller;

import com.eshang.aop.learning.annotation.Eshang;
import com.eshang.aop.learning.annotation.Timing;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author xyx-Eshang
 */
@RestController
@RequestMapping("/student")
public class StudentController {

   @Timing(unit = "s")
   @PostMapping("/testAop")
   public void testAop() {
      System.out.println("现在执行testAop方法");
   }
}

5.4.测试类AopLearningApplicationTests

package com.eshang.aop.learning;

import com.eshang.aop.learning.controller.StudentController;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

@SpringBootTest
class AopLearningApplicationTests {
   @Resource
   StudentController studentController;

   @Test
   void contextLoads() {
      studentController.testAop();
   }

}

5.5.测试结果

自定义注解 java 自定义注解实现_自定义注解 java_08