定义一个注解的方式:
//除了@符号,注解很像是一个接口。
//定义注解的时候需要用到元注解,@Target和@Retention。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
/** 标题 */
//public String title() default "";
//在注解中一般会有一些元素以表示某些值。可以为其制定默认值。没有元素的注解称为标记注解
}
注解须知:
- 注解的可用的类型:所有基本类型、String、Class、enum、Annotation、以上类型的数组形式。
- 元素不能有不确定的值,即要么有默认值,要么在使用注解的时候提供元素的值。而且元素不能使用null作为默认值。
- 注解在只有一个元素且该元素的名称是value的情况下,在使用注解的时候可以省略“value=”,直接写需要的值即可。
下面看一个定义了元素的注解。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
public int id ();
/** 标题元素 */
public String title () default "标题元素";
}
//定义了注解,必然要去使用注解。
public class Utils {
@Test(id = 1, title = "va测试工具标题")
public boolean vaTest (String vaTest) {
if ("vaTest".equals(vaTest)) {
return true;
}
return false;
}
@Test(id = 2)
public String enTest (String enTest) {
return enTest + "java第一";
}
}
使用注解最主要的部分在于对注解的处理,那么就会涉及到注解处理器。
注解处理器:
原理上讲,注解处理器就是通过反射机制获取被检查方法上的注解信息,然后根据注解元素的值进行不同处理。
public static void main (String[] args) {
trackTest(Utils.class);
}
public static void trackTest (Class<?> cl) {
for (Method m : cl.getDeclaredMethods()) {
Test test = m.getAnnotation(Test.class);
if (test != null) {
System.out.println("结果:" + test.id() + " " + test.title());
}
}
}
结合AOP自定义注解
定义注解
import java.lang.annotation.*;
/**
* 自定义操作日志记录注解
*
* @author n
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestAnnotation{
/**
* id
*/
public int id() ;
/**
* 模块标题
*/
public String title() default "";
}
方法上增加注解
@Slf4j
@RestController
@RequestMapping("/admin")
public class AdminController {
@PostMapping(value = "/update/{id}")
@Log(title = "管理",int = 1)
public Object updateAdmin(@PathVariable Long id) {
//操作......
return null;
}
}
Around环绕
/**
* 操作日志记录处理
*
* @author n
*/
@Aspect
@Component
@Order(3)
public class TestAspect {
private static final Logger logs = LoggerFactory.getLogger(TestAspect .class);
// 配置织入点
@Pointcut("@annotation(com.*.log.annotation.TestAnnotation)")
public void TestPointCut () {
}
/**
* 处理完请求后执行
*
* @param pjp 切点
*/
@Around(value = "TestPointCut ()")
public Object doAround (ProceedingJoinPoint pjp) throws Throwable {
// 获得注解
Signature signature = pjp.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
TestAnnotation test= method.getAnnotation(TestAnnotation.class);
if (test!= null) {
//模块标题
String title = test.title();
//id
int id= test.id();
//其他操作
}
Object proceed = null;
try {
proceed = pjp.proceed();
} catch (Throwable e) {
//其他异常操作
throw e;
}
return proceed;
}
}