| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- package com.izouma.nineth.aspect;
- import com.izouma.nineth.annotations.Debounce;
- import com.izouma.nineth.aspect.debounce.DebounceTask;
- import lombok.extern.slf4j.Slf4j;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Pointcut;
- import org.aspectj.lang.reflect.MethodSignature;
- import org.springframework.core.DefaultParameterNameDiscoverer;
- import org.springframework.expression.EvaluationContext;
- import org.springframework.expression.ExpressionParser;
- import org.springframework.expression.spel.standard.SpelExpressionParser;
- import org.springframework.expression.spel.support.StandardEvaluationContext;
- import org.springframework.stereotype.Component;
- import java.lang.reflect.Method;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Optional;
- import java.util.concurrent.Executors;
- import java.util.concurrent.Future;
- import java.util.concurrent.ScheduledExecutorService;
- import java.util.concurrent.TimeUnit;
- @Aspect
- @Component
- @Slf4j
- public class DebounceAspect {
- private DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer();
- private HashMap<String, Future<Void>> debounceStore = new HashMap<>();
- private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(10);
- private Map<String, Long> debounceCounter = new HashMap<>();
- @Pointcut("@annotation(com.izouma.nineth.annotations.Debounce)")
- public void debouncePointCut() {
- }
- @Around(value = "debouncePointCut() && @annotation(debounce)")
- public synchronized void debounce(ProceedingJoinPoint joinPoint, Debounce debounce) {
- ExpressionParser parser = new SpelExpressionParser();
- EvaluationContext context = new StandardEvaluationContext(joinPoint.getSignature());
- MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
- Method method = methodSignature.getMethod();
- String[] paramNames = nameDiscoverer.getParameterNames(method);
- Object[] args = joinPoint.getArgs();
- for (int i = 0; i < args.length; i++) {
- context.setVariable(paramNames[i], args[i]);
- }
- String key = Optional.ofNullable(parser.parseExpression(debounce.key()).getValue(context)).map(Object::toString)
- .orElse("default");
- Future<Void> future = debounceStore.get(key);
- long lastRun = debounceCounter.getOrDefault(key, 0L);
- if (future != null && !future.isDone()) {
- if (System.currentTimeMillis() - lastRun > debounce.delay()) {
- debounceCounter.put(key, System.currentTimeMillis());
- } else {
- future.cancel(false);
- }
- }
- debounceStore.put(key, executorService.schedule(new DebounceTask(joinPoint, (Void) -> {
- debounceCounter.put(key, System.currentTimeMillis());
- return null;
- }), debounce.delay(), TimeUnit.MILLISECONDS));
- }
- }
|