@Target
@Target 主要作用是该类型适用的上下文,比如用在类上、方法上或者字段上,但是一个Target只能有一个ElementType,不能多次出现。并在源代码中由java.lang.annotation.ElementType的枚举常量表示。
enum ElementType
ElementType中的常量在java.lang.annotation.Target元注释中使用,用于指定在哪里可以合法地编写给定类型的注释。
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Annotation type declaration */
ANNOTATION_TYPE,
... ...
... ...
}
For example, the following @Target meta-annotation is illegal:
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
public @interface Bogus {
...
}
@Target 注解源代码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
@Retention
带有@Retention注释类型的注释要保留多长时间。如果注释类型声明中没有保留注释,则保留策略默认为RetentionPolicy.CLASS。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
enum RetentionPolicy
RetentionPolicy是一个enum类型的保留策略,它们与Retention元注释类型一起使用,以指定注释要保留多长时间。
public enum RetentionPolicy {
/**
* 注解将被编译器丢弃。
*/
SOURCE,
/**
* 注解将由编译器记录在类文件中,但不需要在运行时由VM保留。这是默认行为。
*/
CLASS,
/**
* 注解将由编译器记录在类文件中,并在运行时由VM保留,因此它们可能被反射地读取。
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
自定义一个注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AvoidRepeatableCommit {
long timeout() default 6000;
}
然后我们可以通过Aspect对注解进行切面拦截使用。
@Aspect
@Component
@AllArgsConstructor
public class AvoidRepeatableCommitAspect {
/**
* @param point 切点
*/
@Around("@annotation(avoidRepeatableCommit)")
public Object around(ProceedingJoinPoint point, AvoidRepeatableCommit avoidRepeatableCommit) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
String ip = IPUtils.getIpAddr(request);
//获取注解
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
//目标类、方法
String className = method.getDeclaringClass().getName();
String name = method.getName();
// .....
//执行方法
return point.proceed();
}
}
Note
如果在方法上面定义不同的通知,会发生什么?如果发生,执行顺序是什么?比如:
@Around("@annotation(avoidRepeatableCommit)")
@After("@annotation(avoidRepeatableCommit)")
@Before("@annotation(avoidRepeatableCommit)")
public Object around(ProceedingJoinPoint point,
AvoidRepeatableCommit avoidRepeatableCommit)
// will do something...
}
@Around 环绕通知总是会先执行,然后是@Before前置通知,最后只@After后置通知,无论目标方法是否发生异常都会执行。
看到这里,你能自己解释下什么是Annotation吗?