preface

A variety of annotations are used in daily development. Common annotations such as @Override, @param, @Autowired, @Service, etc., come with JDK or Spring frameworks. Classes, methods, variables, parameters, and packages can all be annotated with annotations. Many friends may still be in the use level, know how to use, but do not know the implementation principle, not to write custom annotations to solve problems in real projects.

Let’s talk about the basics of annotations and the use of custom annotations in real projects.

Annotations role

1. Generate documents, the most common in the early days: @return,@param

2. Check at compile time, such as @override, to see if the parent class is overridden

3. Simplify configuration files to make code clearer

 

What are built-in annotations, meta-annotations, and custom annotations?

 

Built-in annotations

Override: Applies to a method that overrides its parent class

Deprecated: Deprecated for a method, attribute, or class

SuppressWarings: Used to suppress compiler warnings and tell the compiler that ignoring them generated a special warning

SafeVarargs: an annotation introduced in jdk1.7 to suppress compiler alarms when using generics and mutable arguments together

 

Yuan comments:

Meta annotations are provided in JDK5.0 and cannot be changed to define other annotations, that is, our custom annotations

@target: Declare the scope of an annotation to be a class, method, method parameter variable, etc. You can also express the scope by enumerating the class ElementType (see source code)

@retention: scope to declare the Retention length of annotations.

SOURCE (valid in SOURCE file)

CLASS (valid when source files are compiled into CLASS CLASS files)

RUNTIME (valid at RUNTIME)

Documented. The role can be Documented by a tool like Javadoc

Inherited: Indicates whether this class can be Inherited

 

Custom annotations

/** ** public @interface annotation name {* type attribute name () default value *} */ @Target({ElementType.METHOD, @retention (retentionPolicy.runtime) // Documented @inherited Public @interface TestAnnotation { String value() default ""; }Copy the code

Simple use of custom annotations

/** * define user annotation */ @target ({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface UserAnnontion  { String name(); int age() default 18; String[] familyMembers() default {}; } / method comment * / * * * @ User (name = "ajie," age = 18, familyMembers = {" XXX, "" XXX," "XXX"}) public void getUser () {}Copy the code

Get annotation information through reflection

public class TestAnnotationReflex { public static void main(String[] args) { try { Class stuClass = Class.forName("com.example.demo.User"); Method method = stuClass.getMethod("getUser"); if(method.isAnnotationPresent(UserAnnontion.class)){ UserAnnontion userAnnontion = method.getAnnotation(UserAnnontion.class); System.out.println("name: " + userAnnontion.name() + ", age: " + userAnnontion.age() + ", familyMembers: " + userAnnontion.familyMembers()[0]); } } catch (Exception e) { e.printStackTrace(); }}}Copy the code

The above is just the basics, many people may not understand the purpose of custom annotations, like simple annotation, or reflection to get annotation information.

 

Next, I’ll use custom annotations in conjunction with Spring AOP, which is used for interceptors, transactions, logging, and permissions. AOP won’t cover this, but logging is an example. In actual project, when debugging or screening abnormal information, log should record the request into the information, whether to use the info (” request parameters “) written as logging, if need to be written, so every time it is easy to miss, and repeated code also is more, under this scenario, you can do a unified log processing plan, This functionality is achieved by using custom annotations and facets.

Custom annotations + facets for unified log handling

 

Custom log annotations

@target (ElementType.METHOD) @Retention(RetentionPolicy.runtime) @Documented Public @Interface OptLog {/** * business * @return */ String business(); * @return */ OptType OptType (); }Copy the code

Declare log aspect components

import com.alibaba.fastjson.JSONObject; import com.example.demo.annotation.OptLog; import com.example.demo.annotation.OptType; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.stereotype.Component; import java.lang.reflect.Method; @Aspect @Component public class OptLogAspect { private static final Logger LOG = LoggerFactory.getLogger(OptLogAspect.class); /** * declare pointcut, Always use this annotation through intercept * / the @pointcut (" @ the annotation (com) example. The demo. The annotation. OptLog) ") public void OptLog () {} @before ("OptLog()") public void doOptLogBefore(JoinPoint proceedingJoinPoint) {log.info (" pre-notification, Before method execution... ); } @after ("OptLog()") public void doOptLogAfter(JoinPoint proceedingJoinPoint) {log.info (" ); } @afterreturning ("OptLog()") public void doOptLogAfterReturning(JoinPoint proceedingJoinPoint) {log.info (" Execute after the method returns the result..." ); } @afterthrowing ("OptLog()") public void doOptLogAfterThrowing(JoinPoint proceedingJoinPoint) {log.info (" Execute after the method throws an exception..." ); ** @param proceedingJoinPoint * @return */ @around ("OptLog()")) public Object optLogAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { Method method = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod(); if (method == null) { return null; } / / access method name String methodName = proceedingJoinPoint. GetSignature (). The getName (); LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer(); / / request parameter name String [] parameterNames = discoverer. GetParameterNames (method); / / request parameter value Object [] paramValues = proceedingJoinPoint. GetArgs (); OptLog optLog = method.getAnnotation(OptLog.class); this.handle(optLog.optType(), optLog.business(), methodName, parameterNames, paramValues); return proceedingJoinPoint.proceed(); } /** * log handling ** @param optType * @param Business * @param methodName * @param parameterNames * @param paramValues */ public void handle(OptType optType, String business, String methodName, String[] parameterNames, Object[] paramValues) { JSONObject jsonObject = new JSONObject(); if (parameterNames ! = null && parameterNames.length > 0) { for (int i = 0; i < parameterNames.length; i++) { jsonObject.put(parameterNames[i], paramValues[i]); } } LOG.info("optType:" + optType + ",business:" + business + ", methodName:" + methodName + ", params:" + jsonObject); }}Copy the code

Control layer running results

@RestController @RequestMapping("/user/") public class UserController { @OptLog(optType = OptType.CREATE,business = @requestMapping ("create") public String createUser(String userName,int age,String address) { System.out.println(" method executing...") ); return "success"; }}Copy the code

The results

15:32:49.494 [HTTP-NIO-8080-exec-2] INFO c.e.d.a.ptLogAspect - [handle,91] -optType :CREATE,business: user information, methodName:createUser, Params :{"address":" address","userName":" age":18} 15:32:49.494 [http-niO-8080-exec-2] INFO c.e.d.a.ptlogAspect - [doOptLogBefore,32] - Pre-notification, executed before method execution... Method in execution... 15:32:49. [HTTP - nio - 8080-495 the exec - 2] INFO C.E.D.A.O ptLogAspect - [doOptLogAfterReturning, 42] - return notice, after the method returns the perform... 15:32:49.495 [HTTP-NIO-8080-exec-2] INFO c.e.d.a.ptLogAspect - [doOptLogAfter,37] - Post-notification, executed after method execution...Copy the code

The last

At the end of the article the author sorted out a lot of information for you! Including Java core knowledge + a full set of architect learning materials and video + first-line factory interview treasure dictionary + resume template interview ali Meituannetease Tencent Xiaomi IQiyi Quick hand bilibili bilibili interview questions +Spring source code collection +Java architecture actual combat e-books and so on! Welcome to pay attention to the public number: the future has light, receive!