前言:在整个Spring框架中提供了许多的注解,今天就来讲讲如何自定义注解
自定义注解内容讲解
@Target (表示该注解可以使用的范围)
@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中
@Retention({RetentionPolicy.Runtime}) 注解 指定注解需要保存多长时间
Runtime 指的是运行期级别
Class 指的是编译期级别
Source 指的是源码级别
@Documented注解
Documented注解表明这个注释是由 javadoc记录的,在默认情况下也有类似的记录工具。 如果一个类型声明被注释了文档化,它的注释成为公共API的一部分。
关于@Target @Document等具体详细讲解,可以参考:https://blog.csdn.net/liang100k/article/details/79515910
我在学习这部分内容的时候看到一个概念,元注解。
元注解即注解的注解,包括@Retention @Target @Document @Inherited四种。
详细内容可以参考:https://www.cnblogs.com/zhi-xing/p/10842978.html
实战部分
在pom引用aop的jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
(1) 定义一个自定义注解的类
package com.test.common;
/**
* @Author tanghh
* @Date 2020/1/16 15:49
*/
import java.lang.annotation.*;
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NewsRecord {
String module() default "";
String[] params() default {};
boolean isDetail() default true;
}
(2)Spring Aop的操作类
package com.test.aspect;
import com.test.common.NewsRecord;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* @Author tanghh
* @Date 2020/1/16 16:05
*/
@Aspect
@Component
public class NewsAspect {
/**
* @Description: 定义一个切点
*/
@Pointcut("@annotation(com.test.common.NewsRecord)")
public void newsRecord() {
}
/**
* @description 方法执行后调用(不区分成功或异常)
**/
@After(value = "@annotation(newsRecord)", argNames = "newsRecord")
public void after(NewsRecord newsRecord) {
System.out.println("111---" + newsRecord.module());
System.out.println("111---" + newsRecord.params());
System.out.println("111---" + newsRecord.isDetail());
}
}
(3)接口调用方法
@NewsRecord(module = "125", params = {"1", "2", "3"}, isDetail = false)
@GetMapping(value = "/getData")
public void listData() {
System.out.println("111111");
}
(4) 接口调用执行结果
其中需要注意一个问题:
(1)小编是SpringBoot项目,其中将运行代码放到 main方法中会出现问题。
见下:
package com.test;
import com.test.common.NewsRecord;
/**
* @Author tanghh
* @Date 2019/12/1 15:52
*/
public class TestCommand {
public static void main(String[]args){
test();
}
@NewsRecord(module = "125",params = {"1","2","3"},isDetail = false)
public static void test(){
System.out.println("111111");
System.out.println("111111");
System.out.println("111111");
}
}
运行出来的结果是:结果出乎意料,没有进aop拦截的方法。后面问了下同事,同事说是Springboot本身有一个启动方法,和当 前这个main方法是同一级的,所以不会进拦截的方法,换成接口访问就行了。