Java custom annotations in action
What are annotations?
Annotations are written in a.java file using @interface as the keyword, so annotations are a Java data type; Annotations A feature introduced since JDK1.5 to annotate classes, interfaces, methods, properties, method parameters, and so on.
The role of annotations
Annotations have the following four functions:
- Generate a document: Generate
javadoc
Documents, such as@Documented
; - Compile check: Checking and validating code during compilation, as in
@Override
; - Compile-time processing: Specific processing of code at compile time, such as
@Data
; - Runtime processing: The runtime performs specific processing on code, such as
@Slf4j
;
Annotations and reflections
After defining the annotation, we can retrieve the content of the annotation by reflecting the java.lang.Reflect mechanism. Note: This is only available by reflection if the scope of the annotation is defined as Runtime.
The following are the specific apis:
Method statement | methods |
---|---|
Gets an annotation of a certain type | public <A extends Annotation> A getAnnotation(Class<A> annotationClass); |
Get all annotations (including Inherited annotations in the parent class) | public Annotation[] getAnnotations(); |
Gets annotations for declarations (excluding Inherited annotations in the parent class) | public Annotation[] getDeclaredAnnotations(); |
Determines whether an object is annotated by an annotation | public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) |
Gets all fields declared by a class | public Field[] getDeclaredFields() throws SecurityException; |
Get a method | public Method getMethod(String name, Class<? >... parameterTypes); |
Custom annotation practice
AOP can be used to control permissions, log output and idempotence check.
Take the idempotent one check as an example:
Step 1: Define annotations
package com.wedjg.cloud.finance.aspect.idem;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EnableIdem {
/** * idempotent time interval (seconds) *@return* /
int expired(a) default 3;
}
Copy the code
Step 2: Use annotations
@PostMapping("test")
@EnableIdem
public CommonResult test(@RequestBody DemoDTO dto) {
financeService.test(dto);
return CommonResult.success(true);
}
Copy the code
Step 3: Write the cut
@Aspect
@Component
public class IdempotentAspect {
public static final Log log = LogFactory.get();
public static final String KEY = "Idem|";
@Before("@annotation(com.wedjg.cloud.aspect.idem.EnableIdem)")
public void handle(JoinPoint joinPoint) throws Exception{
// Get parameter values
Object[] args = joinPoint.getArgs();
// Construct the cache key
// The hashcode of the method path + parameter is used as the key, which may be repeated in some cases
// It should be adjusted according to business in actual use
StringBuilder sb = new StringBuilder();
for (Object arg : args) {
sb.append(Convert.toStr(arg));
}
String methodPath = joinPoint.getSignature().getDeclaringTypeName() + CharUtil.DOT + joinPoint.getSignature().getName();
String redisKey = KEY + methodPath + sb.toString().hashCode();
// Save the key to redis. Be careful to keep setNx and EXPIRED atomic;
// If the key already exists, the request was made within the expired() time range. The current request is a duplicate request.
// If the key does not exist, set the current key to redis and set the expiration time.
// Get information about annotations
EnableIdem enableIdem = this.getDeclaredAnnotation(joinPoint);
if(JedisUtil.setnxAndExpire(redisKey, enableIdem.expired(), "1") = =0L) {
throw new BaseException("Operation too frequent, please try again later!"); }}/** * Get the annotation declared in the method **@param joinPoint
* @return
* @throws NoSuchMethodException
*/
public EnableIdem getDeclaredAnnotation(JoinPoint joinPoint) throws NoSuchMethodException {
// Get the method name
String methodName = joinPoint.getSignature().getName();
// reflection gets the target classClass<? > targetClass = joinPoint.getTarget().getClass();// Get the parameter type of the methodClass<? >[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();// Get method details based on class, method, parameter type (overload)
Method objMethod = targetClass.getMethod(methodName, parameterTypes);
// Get the annotation information for the method definition
EnableIdem annotation = objMethod.getDeclaredAnnotation(EnableIdem.class);
/ / return
returnannotation; }}Copy the code
Refer to the article
- Java custom Annotation Annotation details
- Java Basics – Annotation mechanism details
- Redis operates both setnx and EXPIRE
- The results of one or multiple requests initiated by the user for the same operation are consistent, without side effects caused by multiple clicks ↩