Reasons and Solutions of Executing SpringAop @ Around Twice
- 2021-11-01 03:10:47
- OfStack
In use
AOP
When logging around notifications, it is found that
@Around
Method is executed twice. Although the surrounding notification would have been executed twice here, it is normally executed once before and once after the tangent method, but in reality, it is executed twice before and twice after the tangent method.
The text is not easy to understand, or write 1 code:
@Around("logPointCut()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
logger.debug("==========Request log==========");
long startTime = System.currentTimeMillis();
Object ob = pjp.proceed();
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//JSONObject ipInfo = JSONObject.fromObject(URLDecoder.decode(WebUtils.getCookie(request,"IP_INFO").getValue(),"utf-8"));
//logger.debug("IP: {}", ipInfo.get("ip"));
//logger.debug("CITY {}", ipInfo.get("city"));
logger.debug("IP: {}", BlogUtil.getClientIpAddr(request));
logger.debug("REQUEST_URL: {}", request.getRequestURL().toString());
logger.debug("HTTP_METHOD: {}", request.getMethod());
logger.debug("CLASS_METHOD: {}", pjp.getSignature().getDeclaringTypeName() + "."
+ pjp.getSignature().getName());
//logger.info(" Parameter : " + Arrays.toString(pjp.getArgs()));
logger.debug("USE_TIME: {}", System.currentTimeMillis() - startTime);
logger.debug("==========Request log end==========");
return ob;
}
Then refresh the page below 1, and get the following log:
As you can see, although it was refreshed only once, the log was output twice, which should not be. Then through breakpoint debugging, it is discovered that it is because in the
Controller
Used in the
@ModelAttribute
@ModelAttribute
public void counter(Model model) {
counter.setCount(counter.getCount() + 1);
model.addAttribute("count", counter.getCount());
}
@ModelAttribute
The annotation method will be found in the
Controller
Method is executed once before it is executed, and I put it in the
Controller
And intercepts all
Controller
The method in,
This leads to:
1. First, the page requests to
Controller
, execution
@ModelAttribute
The method annotated will be used at this time
AOP
Intercepted once.
2. Finish execution
@ModelAttribute
After the method is annotated, execute the
@RequestMapping
The method of annotation is again
AOP
Intercepted once.
Therefore, there will be two log outputs.
Solution:
1. Will
Controller
In
@ModelAttribute
Method, extract it and put it in
@ControllerAdvice
Medium.
2. Right
AOP
Interception rules add annotation matching, for example:
execution(public * com.blog.controller.*.*(..)) && (@annotation(org.springframework.web.bind.annotation.RequestMapping))
&& (@annotation(org.springframework.web.bind.annotation.RequestMapping
Indicates that this will only intercept
RequestMappping
The method of annotation.
Note:
If it is a 1 method
a()
Call a method in the same class
b()
If the method
a()
If you do interception,
AOP
Will only intercept
a()
Without intercepting
b()
, because ah
a()
The call to b () is made through the
this.b()
Called by the
AOP
What is really executing is the generated proxy class, which is passed through
this
Naturally, you can't intercept methods
b()
It's over.
Understand the use and attention of Spring @ Around
Note:
1.
@ModelAttribute
0
Sequence of section annotations
@ModelAttribute
1
@Around
(The method to be proxy executes in it)
@AfterReturning
@after
2. No
@Around
The method execution exception to be proxy will be
@AfterThrowing
Capture;
3. In
@Around
How to Perform Method Execution to Proxy
@Around("execution(* cn.com.xalead.spring.MeInterface.*(..)) || execution(* cn.com.xalead.spring.KingInterface.*(..))")
public Object test(ProceedingJoinPoint proceeding) {
Object o = null;
try {
// Execute
o = proceeding.proceed(proceeding.getArgs());
} catch (Throwable e) {
e.printStackTrace();
}
return o;
}