先了解一下自定义注解
自定义注解demo
注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。
自定义注解及其应用
1)、定义一个最简单的注解
public @interface MyAnnotation {
//......
}
2)、把注解加在某个类上:
@MyAnnotation
public class AnnotationTest{
//......
}
Java中提供了四种元注解,专门负责注解其他的注解,分别如下:
@Retention元注解,表示需要在什么级别保存该注释信息(生命周期)。可选的RetentionPoicy参数包括:
RetentionPolicy.SOURCE: 停留在java源文件,编译器被丢掉
RetentionPolicy.CLASS:停留在class文件中,但会被VM丢弃(默认)
RetentionPolicy.RUNTIME:内存中的字节码,VM将在运行时也保留注解,因此可以通过反射机制读取注解的信息
@Target元注解,默认值为任何元素,表示该注解用于什么地方。可用的ElementType参数包括
ElementType.CONSTRUCTOR: 构造器声明
ElementType.FIELD: 成员变量、对象、属性(包括enum实例)
ElementType.LOCAL_VARIABLE: 局部变量声明
ElementType.METHOD: 方法声明
ElementType.PACKAGE: 包声明
ElementType.PARAMETER: 参数声明
ElementType.TYPE: 类、接口(包括注解类型)或enum声明
@Documented注解将注解包含在JavaDoc中
@Inheried注解允许子类继承父类中的注解
以下写了一个模拟注解的案例:
首先写一个自定义注解@MyAnnotation,代码如下所示:
package com.pcict.anotation.test;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
public @interface MyAnnotation {
// 为注解添加属性
String color();
String value() default "我是XXX"; // 为属性提供默认值
int[] array() default { 1, 2, 3 };
Gender gender() default Gender.MAN; // 添加一个枚举
// 添加枚举属性
MetaAnnotation metaAnnotation() default @MetaAnnotation(birthday = "我的出身日期为1988-2-18");
}
写一个枚举类Gender,模拟注解中添加枚举属性,代码如下所示:
package com.pcict.anotation.test;
public enum Gender {
MAN {
public String getName() {
return "男";
}
},
WOMEN {
public String getName() {
return "女";
}
}; // 后面记得有“;”
public abstract String getName();
}
写一个注解类MetaAnnotation,模拟注解中添加注解属性,代码如下:
package com.pcict.anotation.test;
public @interface MetaAnnotation {
String birthday();
}
最后写注解测试类AnnotationTest,代码如下:
// 调用注解并赋值
@MyAnnotation
(metaAnnotation =
@MetaAnnotation(birthday = "我的出身日期为1988-2-18")
, value = "owlfeng"
,color = "red", array = {23, 26 })
public class AnnotationTest {
public static void main(String[] args) {
// 检查类AnnotationTest是否含有@MyAnnotation注解
if (AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)) {
// 若存在就获取注解
MyAnnotation annotation = (MyAnnotation) AnnotationTest.class
.getAnnotation(MyAnnotation.class);
System.out.println(annotation);
// 获取注解属性
System.out.println(annotation.color());
System.out.println(annotation.value());
// 数组
int[] arrs = annotation.array();
for (int arr : arrs) {
System.out.println(arr);
}
// 枚举
Gender gender = annotation.gender();
System.out.println("性别为:" + gender);
// 获取注解属性
MetaAnnotation meta = annotation.metaAnnotation();
System.out.println(meta.birthday());
}
}
}
运行AnnotationTest,输出结果为:
@com.example.demo.annotation.MyAnnotation(gender=MAN, metaAnnotation=@com.example.demo.annotation.MetaAnnotation(birthday=我的出身日期为1988-2-18), value=owlfeng, array=[23, 26], color=red)
red
owlfeng
23
26
性别为:MAN
我的出身日期为1988-2-18
Process finished with exit code 0
springboot 实现
pom.xml (maven)
<!--切面注解-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.13</version>
</dependency>
<!--springboot aop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
创建基本日志类型
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
String value() default "";
}
创建日志切面
@Aspect
@Component
public class LogAspect {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private LogService logService; // save
//切点选择为 @LOG注解过的类
@Pointcut("@annotation(cn.tycoding.common.annotation.Log)")
public void pointcut() {
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws JsonProcessingException {
Object result = null;
long beginTime = System.currentTimeMillis();
try {
result = proceedingJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
throw new GlobalException(throwable.getMessage());
}
//获取Request请求
HttpServletRequest request = HttpContextUtil.getHttpServletRequest();
//设置IP地址
String ip = IPUtil.getIpAddr(request);
//记录时间(毫秒)
long time = System.currentTimeMillis() - beginTime;
SysLog log = new SysLog();
log.setIp(ip);
log.setTime(time);
logService.saveLog(proceedingJoinPoint, log);
return result;
}
}
logService 保存方法
@Override
public void saveLog(ProceedingJoinPoint proceedingJoinPoint, SysLog log) throws JsonProcessingException {
MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
Method method = signature.getMethod();
Log annotation = method.getAnnotation(Log.class);
if (annotation != null) {
//注解上的描述
log.setOperation(annotation.value());
}
//请求的类名
String className = proceedingJoinPoint.getTarget().getClass().getName();
//请求方法名
String methodName = signature.getName();
log.setMethod(className + "." + methodName + "()");
//请求的方法参数
Object[] args = proceedingJoinPoint.getArgs();
//请求的方法参数名称
LocalVariableTableParameterNameDiscoverer d = new LocalVariableTableParameterNameDiscoverer();
String[] parameterNames = d.getParameterNames(method);
if (args != null && parameterNames != null) {
StringBuilder params = new StringBuilder();
params = handleParams(params, args, Arrays.asList(parameterNames));
log.setParams(params.toString());
}
log.setCreateTime(new Date());
log.setLocation(AddressUtil.getAddress(log.getIp()));
this.save(log);
}
controller
@Log("查询商品")
@GetMapping
public Result selectById(){
return new Result(true, StatusCode.OK,"查询成功",goodsService.selectList(null));
}
上面使用的具体工具类 我之后会一一列举出来
大家先看看这种方式