元注解就是注解的注解,用来描述注解的
- @Retention 定义该注解的生命周期
- RetentionPolicy.SOURCE :作用于源码阶段,比如常见的 @Override, @SuppressWarnings;
- RetentionPolicy.CLASS :作用于字节码阶段
- RetentionPolicy.RUNTIME :作用于运行阶段
- @Target 定义该注解的作用范围
- ElementType.TYPE :用于注解到类,接口、枚举类
- ElementType.FIELD:字段,包括枚举类常量
- ElementType.METHOD:方法声明
- ElementType.PARAMETER:参数声明
- ElementType.CONSTRUCTOR:构造器声明
- ElementType.LOCAL_VARIABLE :局部变量声明
- ElementType.ANNOTATION_TYPE :用于注解声明,即注解的注解,元注解
- ElementType.PACKAGE :包声明
- 其他注解
- @Document 注解将生成到javadoc中
- @Deprecated 表示过时的类
- @Inherited 是否允许子类继承该注解
- @SuppressWarnings 编译器忽略掉无法识别的警告名
- @Override 标注的方法重载了父类的方法
实例代码
/**
* @author FWG
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.PARAMETER})
@Documented
public @interface PayableAnnotation
{
String businessName();
}
获取注解值
@MyAnnotation1(name = "abc")
public class Demo1 {
@MyAnnotation1(name = "xyz")
private Integer age;
@MyAnnotation2(model = TranscationModel.Read)
public void list() {
System.out.println("list");
}
@MyAnnotation3(models = {TranscationModel.Read, TranscationModel.Write})
public void edit() {
System.out.println("edit");
}
public void hello1(@IsNotNull(true) String name) {
System.out.println("hello:" + name);
}
}
//获取类上的注解
MyAnnotation1 annotation1 = Demo1.class.getAnnotation(MyAnnotation1.class);
System.out.println(annotation1.name());//abc
// 获取方法上的注解
MyAnnotation2 myAnnotation2 = Demo1.class.getMethod("list").getAnnotation(MyAnnotation2.class);
System.out.println(myAnnotation2.model());//Read
// 获取属性上的注解
MyAnnotation1 myAnnotation1 = Demo1.class.getDeclaredField("age").getAnnotation(MyAnnotation1.class);
System.out.println(myAnnotation1.name());// xyz
// 获取参数上的注解
for (Parameter parameter : demo3.getClass().getMethod("hello1", String.class).getParameters()) {
IsNotNull annotation = parameter.getAnnotation(IsNotNull.class);
if(annotation != null){
System.out.println(annotation.value());//true
}
}
3.使用实例
3.1 定义注解接口
import java.lang.annotation.*;
/**
* 打印出操作日志
* @author
* @create 2019/11/4
*/
//定义该注解的作用范围
@Target({ElementType.TYPE, ElementType.METHOD})
//定义该注解的生命周期
@Retention(RetentionPolicy.RUNTIME)
//注解将生成到javadoc中
@Documented
public @interface SystemLog {
/**
* 日志内容
* @return
*/
String message() default "";
}
3.2 实现接口
import com.example.shiro.config.SystemLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* 日志拦截
* @author
* @create 2019/11/4
*/
@Slf4j
//使用order属性,设置该类在spring容器中的加载顺序
@Order(10)
//作用是把当前类标识为一个切面供容器读取
@Aspect
//把普通类实例化到spring容器中
@Component
public class OuterServiceAop {
@Pointcut("@annotation(com.example.shiro.config.SystemLog)")
public void serviceAop(){}
@Before("serviceAop()")
public void doBefore(JoinPoint joinPoint) {
log.info("前置通知");
}
@After("serviceAop()")
public void doAfter(JoinPoint joinPoint) {
log.info("后置通知");
}
@AfterReturning(pointcut = "serviceAop()", returning = "res")
public void doAfterReturning(JoinPoint joinPoint, Object res) {
log.info("日志返回通知");
//请求方法
String method = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
log.info("method:"+ method);
//日志描述
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method1 = signature.getMethod();
SystemLog annotation = method1.getAnnotation(SystemLog.class);
String message = annotation.message();
log.info(message);
}
@AfterThrowing(pointcut = "serviceAop()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
log.info("异常通知");
log.info("异常信息:" + e.getMessage());
}
}
在需要的类或方法中增加注解
import com.example.shiro.config.SystemLog;
import com.example.shiro.entity.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.shiro.common.BaseController;
/**
* <p>
* 前端控制器
* </p>
*
* @author
* @since 2019-11-01
*/
@RestController
@RequestMapping("/user")
public class UserController extends BaseController {
@PostMapping("/login")
@SystemLog(message = "用户登录")
public String login(User user) {
...
}
}