Download this chapter source code
โค๏ธ The source of this chapter has been shared on github
What is AOP
- AOP is also called
Section-oriented programming
, designed to improve by allowing separation of crosscutting concernsmodular
. The popular understanding is to encapsulate the logic code that has nothing to do with the business, but is called by the business module together, and form a section to make the original business more powerful, that isTo enhance
And,Reduce duplicate code
.To reduce
Between modulesThe coupling
To facilitate later operation and maintenance
Static proxy and dynamic proxy difference
- The key of AOP implementation lies in the AOP proxy automatically created by AOP framework. AOP proxy can be divided into static proxy and dynamic proxy
Static agent
An AOP proxy class is compiled using commands provided by the AOP framework, thus generating AOP proxy classes at compile timeCompile-time enhancement
A dynamic proxy
AOP dynamic proxy classes are “temporarily” generated in memory at runtime with the help of JDK dynamic proxy, CGLIB, etc., hence the termRuntime enhancement
Cglib and JDK dynamic proxy
What are the differences between Cglib and JDK dynamic proxies?
- Cglib dynamic proxy: use
The ASM framework
The class file generated by the proxy object class is loaded in and generated by modifying its bytecodeA subclass
To deal with- Generates a subclass of the specified class that overrides the methods and their enhancements, but because it is inherited, it is best that the class or method does not generate final, because final classes or methods cannot be inherited
- JDK dynamic proxy: Generates one using interceptors (you must implement InvocationHandler) and reflection
The agent interface
Is handled by calling InvokeHandler before invoking the concrete method- JDK dynamic proxies can only be implemented
interface
Generates proxies for classes, not for classes
- JDK dynamic proxies can only be implemented
Cglib and JDK dynamic proxy usage scenarios
- The target object generates the interface using JDK dynamic proxies by default
- If the target object uses an interface, you can force the use of cglib(add < AOP: Aspectj-autoproxy proxyt-target-class=”true”/> in the Spring configuration)
- If the target object does not implement an interface, you must use the Cglib library, which Spring will
automatic
Between JDK dynamic proxy and Cglibconversion
Additional is faster than the JDK
- Underlying cglib is the ASM bytecode generation framework, but bytecode technology generates proxy classes, which were more efficient than using Java reflection prior to JDK 1.6
- After JDK6, the JDK dynamic proxy is gradually optimized, and the efficiency is higher than that of Cglib proxy when the number of calls is relatively small
- Cglib is only efficient when a lot of calls are made, but by 1.8 the JDK was more efficient than Cglib
- Cglib cannot proxy methods that declare final because Cglib dynamically generates proxy objects, immutable classes modified by the final keyword can only be referenced and cannot be modified
The difference between | CGLIB | JDK dynamic proxy |
---|---|---|
The principle of | dynamic Generate a proxyA subclass .Subclasses override All non-final methods of the class to be proxied. The method interception technique in the subclass intercepts all calls to the parent class’s methods, weaving into crosscutting logic that is better than Java’s reflection of JDK dynamic proxiesfast |
Dynamic proxies in the JDK are implemented through reflection class Proxies and the InvocationHandler callback interface, but all classes in the JDK do dynamic proxiesMust be To implement ainterface , that is, only methods defined in the interface implemented by this class can be proxy, which has some limitations in practical programming and uses reflection efficiencyThe slower |
Whether to provide subclass proxy | is | no |
Whether to provide interface proxy | Yes (do not use interface) | Yes (must) |
Additional combat
Rely on
I tested it directly in the Springboot project, spring-core with cglib dependencies
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
Copy the code
code
Method to delegate say:
/ * * *@Description: The class to be proxied@Author: jianweil
* @date: better 2021/12/7 * /
public class HelloWorld {
public String say(boolean say) throws Exception {
System.out.println("Hello Student");
if(! say) {throw new Exception("Wrong answer!);
}
return "That's right!; }}Copy the code
The test class:
package com.ljw.springbootaop.proxy.cglib;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/ * * *@Description: Test cGLIb *@Author: jianweil
* @date: 2021/12/7 arieh * /
@Slf4j
public class Enhancer2Test {
/** ** */
private static void before(a) {
log.info("before method invoke...");
}
/** ** after notification */
private static void after(a) {
log.info("after method invoke...");
}
/** * Exception notification */
private static void exception(a) {
log.info("exception method invoke...");
}
/** * notifies */ before the method returns
private static void beforeReturning(a) {
log.info("beforeReturning method invoke...");
}
public static void main(String[] args) throws Exception {
HelloWorld hello = new HelloWorld();
There are other callback methods, too. Here we test the MethodInterceptor callback: MethodInterceptor
HelloWorld proxyHW = (HelloWorld) Enhancer.create(hello.getClass(), new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object result = null;
try {
// Pre-notification
before();
result = method.invoke(hello, objects);
// post notification
after();
} catch (Exception e) {
// Exception notification
exception();
} finally {
// notification before method return
beforeReturning();
}
returnresult; }});//String result = proxyHW.say(true);
String result = proxyHW.say(false); System.out.println(result); }}Copy the code
- Create the proxy class using Enhancer
- Here we use a MethodInterceptor callback: MethodInterceptor, and a few others that you’ll have time to explore
- The proxied class cannot be the final class
test
- String result = proxyhw. say(true) :
15:57:01758. [main] INFO com.ljw.springbootaop.proxy.cglib.Enhancer2Test - before method invoke...
Hello Student
15:57:01760. [main] INFO com.ljw.springbootaop.proxy.cglib.Enhancer2Test - after method invoke...
15:57:01760.[main] INFO com.ljw.springbootaop.proxy.cglib.Enhancer2Test - beforeReturning method invoke... That's right!Copy the code
- String result = proxyhw.say (false) :
Connected to the target VM, address: '127.0.0.1:53976'.transport: 'socket'
15:55:42.136 [main] INFO com.ljw.springbootaop.proxy.cglib.Enhancer2Test - before method invoke...
Hello Student
15:55:42.139 [main] INFO com.ljw.springbootaop.proxy.cglib.Enhancer2Test - exception method invoke...
15:55:42.139 [main] INFO com.ljw.springbootaop.proxy.cglib.Enhancer2Test - beforeReturning method invoke...
null
Copy the code
JDK dynamic proxy deployment
Rely on
The JDK environment comes with the JAR packages required by the JDK dynamic proxy.
code
Interface class:
public interface Animal {
void doWhat(boolean isDo) throws Exception;
}
Copy the code
Implementation class:
public class Cat implements Animal {
@Override
public void doWhat(boolean isDo) throws Exception {
if(! isDo) { System.out.println("Cat only eats!");
throw new Exception("Cat only eats.");
} else {
System.out.println("Cat can meow, meow, meow."); }}}Copy the code
Proxy implementation class:
package com.ljw.springbootaop.proxy.jdk;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/ * * *@Description: todo
* @Author: jianweil
* @date: 2021/12/7 16:06 * /
@Slf4j
public class AnimalInvacationHandler implements InvocationHandler {
private final Animal animal;
public AnimalInvacationHandler(Animal animal) {
this.animal = animal;
}
/** * -proxy: proxy object, newProxyInstance return object * - method: called method * - args: method parameters */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try {
// Pre-notification
before();
result = method.invoke(animal, args);
// post notification
after();
} catch (Exception e) {
// Exception notification
exception();
} finally {
// notification before method return
beforeReturning();
}
return result;
}
private void before(a) {
log.info("before method invoke...");
}
private void after(a) {
log.info("after method invoke...");
}
private void exception(a) {
log.info("exception method invoke...");
}
private void beforeReturning(a) {
log.info("beforeReturning method invoke..."); }}Copy the code
The test class:
/ * * *@Description: Test JDK dynamic proxy *@Author: jianweil
* @date: 2021/12/7 16:08 * /
public class InvacationHandlerTest {
public static void main(String[] args) throws Exception {
Animal cat = new Cat();
/** * interfaces: interfaces that the dynamic proxy class implements */
Animal animal = (Animal) Proxy.newProxyInstance(cat.getClass().getClassLoader(), Cat.class.getInterfaces(), new AnimalInvacationHandler(cat));
animal.doWhat(true);
//animal.doWhat(false);}}Copy the code
test
- animal.doWhat(true);
16:28:04105.[main] INFO com.ljw.springbootaop.proxy.jdk.AnimalInvacationHandler - before method invoke... Cat can meow, meow, meow16:28:04107. [main] INFO com.ljw.springbootaop.proxy.jdk.AnimalInvacationHandler - after method invoke...
16:28:04107. [main] INFO com.ljw.springbootaop.proxy.jdk.AnimalInvacationHandler - beforeReturning method invoke...
Copy the code
- animal.doWhat(false);
16:28:36.455[main] INFO com.ljw.springbootaop.proxy.jdk.AnimalInvacationHandler - before method invoke... Cat only eats!16:28:36.457 [main] INFO com.ljw.springbootaop.proxy.jdk.AnimalInvacationHandler - exception method invoke...
16:28:36.457 [main] INFO com.ljw.springbootaop.proxy.jdk.AnimalInvacationHandler - beforeReturning method invoke...
Copy the code
Differences between Spring AOP and Aspectj
-
Spring AOP
Spring AOP is a dynamic proxy that generates target classes at run time through a proxy. By default, if an interface is used, JDK dynamic proxy is used. If no interface is used, CGLIB is used
- Spring AOP aims to address the most common AOP (method weaving) in enterprise development, simply
Method to weave
- Spring AOP need
Dependent IOC container
Can only work with the Spring container and is implemented using pure Java code - In terms of performance, since Spring AOP is implemented based on dynamic proxies, the need to generate proxy instances when the container is started, and the depth of the stack in method calls makes Spring AOP’s
Performance is
AspectJpoor
- Spring AOP
Support for annotations
To make it easier to create and configure aspects using the @Aspect annotation.
-
AspectJ
- AspectJ is a static proxy that compiles aspect code to object code at compile time. This is done by modifying the code. There are several weaving opportunities:
- Compile-time weaving: If class A adds an attribute using AspectJ and class B references it, the scenario needs to be compile-time weaving otherwise class B won’t Compile.
- Post-compile weaving: that’s where the.class file is generated, or the weaving jar file is generated, and we need to improve the weaving.
- Load-time weaving: Weaving occurs when classes are being loaded, and there are several common ways to do this.
- 1. Custom class loaders do this, which is probably the easiest way to load classes before they are woven into the JVM, so you can define the behavior at load time.
- Specify aspectJ-provided agent at JVM startup time:
-javaagent:xxx/xxx/aspectjweaver.jar
.
- AspectJ can do things Spring AOP can’t; it is a complete solution to AOP programming that AspectJ supports
All pointcuts
And not just method weaving. - Because AspectJ does the weaving before it actually runs, the classes it generates are
No additional runtime overhead
the - You need to create the facets through an.AJ file, and you need to use ajC (Aspect compiler) to compile the code.
- AspectJ is a static proxy that compiles aspect code to object code at compile time. This is done by modifying the code. There are several weaving opportunities:
Spring AOP | AspectJ |
---|---|
Implemented in pure Java | Extended implementation using the Java programming language |
No separate compilation process is required | The AspectJ compiler (AJC) is required unless LTW is set up |
Can only useThe runtime weave |
Runtime weaving is not available. supportCompile time, compile time, and load time weave |
Not very functional – only supportedMethod level weaving |
More powerful – You can weave fields, methods, constructors, static initializers, final classes/methods, etc. |
It can only be implemented on beans managed by the Spring container | This can be implemented on all domain objects |
Only supportmethods Execution pointcut |
supportAll pointcuts |
Proxies are created by target objects, and facets are applied to them | Aspects are woven directly into the code before the application is executed (at run time) |
Than the AspectJslow Much more |
better The performance of the |
Easy to learn and apply | It’s more complicated than Spring AOP |
myth
Used to think
AspectJ is part of Spring AOP because Spring AOP uses AspectJ’s annotations.- Aspects are used to define aspects, pointcuts are used to define pointcuts, and Advice is used to define enhanced processing.
Spring AOP uses Aspect annotations (@aspect, @pointcut, @before, etc.), but it doesn't use its compiler or weavers. It is implemented using JDK dynamic proxies and CGLIB, which generate proxy classes at run time.
- To enable Spring’s support for the configuration of the @AspectJ aspect, and to ensure that target beans in the Spring container are automatically enhanced by one or more aspects, you must add the following configuration to the Spring configuration file: < AOP: Aspectj-autoproxy /> support is enabled by default in older versions of SpringBoot and does not need to be configured.
JDK dynamic proxy, Cglib, Spring AOP and Aspectj
- Spring AOP and Aspectj are two frameworks that implement AOP
- Spring AOP uses dynamic proxies
- Dynamic proxies are implemented in two underlying technologies:
- JDK dynamic proxies (target classes with default interfaces use JDK dynamic proxies)
- Cglib (used by target classes with or without interfaces)
- Spring AOP uses the annotations provided by the Aspectj package, but the underlying compiler and weaver are not Aspectj
- Dynamic proxies are implemented in two underlying technologies:
- Aspectj uses static proxies
6. AOP related concepts
Section (Aspect)
- The section is one
Modularity of crosscutting concerns
, a facet can contain different enhancements of the same type. For example, transaction processing and logging can be understood as two facets. - Section by
The breakthrough point
andnotice
Component, which contains both the definition of crosscutting logic and the definition of pointcuts. - Spring AOP is the framework responsible for implementing the aspect, weaving the crosscutting logic defined by the aspect into the join points specified by the aspect.
@Component
@Aspect
public class LogAspect {}Copy the code
Target Object
- Target object means will
The enhanced object
That is, the class object containing the main business logic. Or an object notified by one or more facets
JoinPoint
- A specific point in the execution of a program, e.g
Method call
Or a specific exception is thrown. Join points are determined by two pieces of information:- Method (indicates the program execution point, i.e. at which target method)
- Relative point (indicates orientation, i.e. where the target method is located, e.g. before, after, etc.)
- In a nutshell,
Join points are the program execution points that are intercepted
Because of Spring AOPOnly join points of method types are supported
So join points are methods that are intercepted in Spring.
@Before("pointcut()")
public void log(JoinPoint joinPoint) { // the JoinPoint argument is the JoinPoint
}
Copy the code
Point (PointCut)
Pointcuts are conditional definitions that intercept join points
. How pointcut expressions match join points is at the heart of AOP, and Spring uses AspectJ pointcut syntax by default.- In general, all methods can be considered join points, but we do not want to add advice to all methods, and
The purpose of a pointcut is to provide a set of rules (described using AspectJ Pointcut Expression Language) to match join points
To add notifications to join points that meet the rule.
- The matching rules for pointcuts are
com.ljw.test.aop.service
All functions of all classes under the package.
@Pointcut("execution(* com.ljw.test.aop.service.. *. * (..) )"
public void Pointcut(a) {}
Copy the code
The entire expression can be divided into four parts:
- The first * : indicates the return type, and the * indicates all types
- Packet name: indicates the name of the packet to be intercepted, followed by.. Said the current bag and the bag of all child bag, com. LJW. Test. Aop. Children of service package, package of all classes of methods.
- The second * : indicates the class name, and the * indicates all classes.
- * (..) The final asterisk represents the method name, the asterisk represents all methods, the parenthesis represents method arguments, and the two periods represent any arguments
- All method facets for all classes in the com.ljw.controller package
@Pointcut("execution(public * com.ljw.controller.*.*(..) )"
Copy the code
- For the UserController class section only
@Pointcut("execution(public * com.ljw.controller.UserController.*(..) )"
Copy the code
- Unified pointcuts for all method facets of all classes in com.ljw and its subpackages
@Pointcut("execution(* com.ljw.controller.*.*(..) )"
Copy the code
Notice (Advice)
- Notification is after interception at the join point
The code to execute
, including around, before, and after types of notifications. - The Spring AOP framework implements the notification model with interceptors and maintains a chain of interceptors centered around join points.
JoinPoint = JoinPoint; // JoinPoint = JoinPoint; // JoinPoint = JoinPoint
@Before("pointcut()")
public void log(JoinPoint joinPoint) {}Copy the code
Weave (has)
- Weaving is the process of connecting facets to business logic objects and creating a notification broker.
- Weaving can be done at compile time, class load time, and run time.
- Weaving at compile time is a static proxy, while weaving at run time is a dynamic proxy.
Enhancer (Advisor)
- The Advisor is another implementation of the aspect, weaving the advice into the target object in a more complex way, and is an assembler that wraps the advice into a more complex aspect.
- Advisors consist of pointcuts and Advice.
- The concept of Advisor comes from Spring’s support for AOP and has no equivalent in AspectJ. The Advisor is like a small self-contained aspect that has only one notification. The aspect itself is represented by a Bean, and a default interface must be implemented.
// AbstractPointcutAdvisor is the default interface
public class LogAdvisor extends AbstractPointcutAdvisor {
private Advice advice; // Advice
private Pointcut pointcut; / / point
@PostConstruct
public void init(a) {
/ / AnnotationMatchingPointcut is according to modify the class and method annotations to intercept point.
this.pointcut = new AnnotationMatchingPointcut((Class) null, Log.class);
/ / notice
this.advice = newLogMethodInterceptor(); }}Copy the code
Seven, AOP common annotations
- @aspect: Identifies the current class as an Aspect for the container to read
- Pointcut: A Pointcut is the definition of a condition that intercepts join points, which in a program is primarily written as a Pointcut expression
- @before: Identifies a front-enhanced method, equivalent to the BeforeAdvice functionality
- AfterReturning: AfterReturning enhancement, equivalent to AfterReturningAdvice, executed when methods exit
- AfterThrowing: Exception throw enhancement, equivalent to ThrowsAdvice
- @after: Final enhancement, whether an exception is thrown or a normal exit
- @around: Surround-enhanced, equivalent to MethodInterceptor
Eight, AOP execution order
Successful execution:
Graph LR Around --> Before Before --> Business Business --> AfterReturning AfterReturning --> After After --> Around
Execution failed (note that there is no Around) :
Graph LR Around Before --> Before --> Business business --> AfterThrowing AfterThrowing --> After
AOP practice: log collection
Demand analysis
- Logging uses annotations to make business code less intrusive
- Logs can be divided into modules
- Logs record different operations
- Logs record the IP addresses of operations
- Logs need to be persisted to the database
Log notes
/ * * *@Description: Log annotations *@Author: jianweil
* @date: 2021/12/6 and * /
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
/** * module */
String module(a) default "";
/** * Action category */
ActionType actionType(a) default ActionType.OTHER;
/** * Operator type */
OperatorType operatorType(a) default OperatorType.MANAGE;
/** * Whether to save the request parameters */
boolean saveParameter(a) default true;
}
Copy the code
The log section
/ * * *@Description: Operation log processing *@Author: jianweil
* @date: 2021/12/6 my * /
/ / section
@Aspect
@Component
public class LogAspect {
@Resource
private ApplicationContext appContext;
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
/** * Configure the pointcut */
@Pointcut("@annotation(com.ljw.springbootaop.aspect.annotation.Log)")
public void logPointCut(a) {}/** * notification: execute ** after processing the request@paramJoinPoint joinPoint */
@AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) {
handleLog(joinPoint, null, jsonResult);
}
/** * Notification: intercept abnormal operation **@paramJoinPoint connection point *@paramE * /
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
handleLog(joinPoint, e, null);
}
protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) {
try {
// Get comments
Log controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null) {
return;
}
// Get the current login user
LoginUser loginUser = appContext.getBean(LoginUser.class);
// *======== database log =========*//
SysOperLog operLog = new SysOperLog();
//ๆจกๆid
operLog.setOperId((long) new Random().nextInt());
// Status 1 is successful
operLog.setStatus(1);
// The requested address
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
operLog.setOperIp(ip);
// Return parameters
operLog.setJsonResult(JSON.toJSONString(jsonResult));
operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
if(loginUser ! =null) {
operLog.setOperName(loginUser.getUsername());
}
if(e ! =null) {
operLog.setStatus(0);
operLog.setErrorMsg(StrUtil.sub(e.getMessage(), 0.2000));
}
// Set method name
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
operLog.setMethod(className + "." + methodName + "()");
// Set the request mode
operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
// Handle setting the parameters on the annotations
getControllerMethodDescription(joinPoint, controllerLog, operLog);
// Save the database
log.info("# # # # # # # # # # # # # # # # # # # # # # # # # # # to save database # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #");
this.saveDB(operLog);
log.info("# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #");
} catch (Exception exp) {
// Record local exception logs
log.error("== Pre-notification exception ==");
log.error("Exception message :{}", exp.getMessage()); exp.printStackTrace(); }}/** * Get the method description in the annotation for the Controller layer annotation **@paramThe log log *@paramOperLog Operation log *@throws Exception
*/
public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog) throws Exception {
// Set the action
operLog.setActionType(log.actionType().ordinal());
// Set the title
operLog.setModule(log.module());
// Set the operator category
operLog.setOperatorType(log.operatorType().ordinal());
// Whether to save request, parameters, and values
if (log.saveParameter()) {
// Get the parameter information and pass it to the database.setRequestValue(joinPoint, operLog); }}/** * get the request parameters and place them in log **@paramOperLog Operation log *@throwsThe Exception Exception * /
private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception {
String requestMethod = operLog.getRequestMethod();
// Post and put requests come out
if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {
String params = argsArrayToString(joinPoint.getArgs());
operLog.setOperParam(StrUtil.sub(params, 0.2000));
} else {
Restful style: {id} Parameter is obtainedHttpServletRequest httpServletRequest = ServletUtils.getRequest(); Map<? ,? > paramsMap = (Map<? ,? >) httpServletRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);// Get other styles
if (paramsMap.isEmpty()) {
HashMap<String, Object> map = new HashMap<>();
Enumeration enu = httpServletRequest.getParameterNames();
while (enu.hasMoreElements()) {
String paraName = (String) enu.nextElement();
map.put(paraName, httpServletRequest.getParameter(paraName));
}
operLog.setOperParam(StrUtil.sub(map.toString(), 0.2000));
} else {
operLog.setOperParam(StrUtil.sub(paramsMap.toString(), 0.2000)); }}}/** * if there are annotations, if so, get */
private Log getAnnotationLog(JoinPoint joinPoint) throws Exception {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if(method ! =null) {
return method.getAnnotation(Log.class);
}
return null;
}
/** ** parameter assembly */
private String argsArrayToString(Object[] paramsArray) {
String params = "";
if(paramsArray ! =null && paramsArray.length > 0) {
for (int i = 0; i < paramsArray.length; i++) {
if(! isFilterObject(paramsArray[i])) { Object jsonObj = JSON.toJSON(paramsArray[i]); params += jsonObj.toString() +""; }}}return params.trim();
}
/** * Determines whether the object needs to be filtered. * *@paramO Object information. *@returnReturn true if the object is to be filtered; Otherwise return false. * /
public boolean isFilterObject(final Object o) {
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse;
}
/** * emulated save database **@param operLog
*/
private void saveDB(SysOperLog operLog) { log.info(operLog.toString()); }}Copy the code
use
/ * * *@Description: Log operation *@Author: jianweil
* @date: 2021/12/6 15:49 * /
@RestController
@RequestMapping("/do")
@Slf4j
public class DoSomethingController {
// Join point: the rule that triggers pointcut configuration when the getXxx method is called
@log (module = "QUERY ", actionType = actionType.QUERY, operatorType = operatorType.MANAGE, saveParameter = false)
@GetMapping
public String getXxx(@RequestParam String param) {
log.info("Get request, parameter: {}", param);
return param;
}
@log (module = "QUERY ", actionType = actionType.QUERY, operatorType = operatorType.MANAGE, saveParameter = true)
@GetMapping("/{param}")
public String getXxx1(@PathVariable String param) {
log.info("Get request, parameter: {}", param);
return param;
}
@log (module = "add operation ", actionType = actionType.INSERT, operatorType = operatorType.MOBILE, saveParameter = true)
@PostMapping
public LoginUser postXxx(@RequestBody LoginUser loginUser) {
log.info("Post request, parameter: {}", loginUser.toString());
return loginUser;
}
@log (module = "modify ", actionType = actionType. UPDATE, operatorType = operatorType. MOBILE, saveParameter = true)
@PutMapping
public LoginUser updateXxx(@RequestBody LoginUser loginUser) {
log.info("Put request, parameter: {}", loginUser.toString());
return loginUser;
}
@log (module = "DELETE ", actionType = actionType.DELETE, operatorType = operatorType.MANAGE, saveParameter = true)
@DeleteMapping("/{param}")
public String deleteXxx(@PathVariable String param) {
log.info("Delete request, parameter: {}", param);
returnparam; }}Copy the code
- ๐๐ป : have harvest, praise encouragement!
- โค๏ธ : Collect articles, easy to look back!
- ๐ฌ : Comment exchange, mutual progress!