1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
| @Aspect @Component @Slf4j public class SplitWorkAspect {
@Pointcut("@annotation(com.demo.SplitWorkAnnotation)") public void needSplit() { }
@Around("needSplit()") public Object around(ProceedingJoinPoint pjp) throws Throwable { Signature signature = pjp.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; Method targetMethod = methodSignature.getMethod(); SplitWorkAnnotation splitWorkAnnotation = targetMethod.getAnnotation(SplitWorkAnnotation.class); Object[] args = pjp.getArgs();
int splitLimit = splitWorkAnnotation.splitLimit(); int splitGroupNum = splitWorkAnnotation.splitGroupNum(); if (args == null || args.length == 0 || splitLimit <= splitGroupNum) { return pjp.proceed(); }
int needSplitParamIndex = -1; for (int i = 0; i < targetMethod.getParameters().length; i++) { Parameter parameter = targetMethod.getParameters()[i]; NeedSplitParam needSplitParam = parameter.getAnnotation(NeedSplitParam.class); if (needSplitParam != null) { needSplitParamIndex = i; break; } }
if (needSplitParamIndex == -1) { return pjp.proceed(); } Object needSplitParam = args[needSplitParamIndex];
if (!(needSplitParam instanceof Object[]) && !(needSplitParam instanceof List) && !(needSplitParam instanceof Set)) { return pjp.proceed(); } boolean notMeetSplitLen = (needSplitParam instanceof Object[] && ((Object[]) needSplitParam).length <= splitLimit) || (needSplitParam instanceof List && ((List) needSplitParam).size() <= splitLimit) || (needSplitParam instanceof Set && ((Set) needSplitParam).size() <= splitLimit); if (notMeetSplitLen) { return pjp.proceed(); }
if (needSplitParam instanceof List) { List<?> list = (List<?>) needSplitParam; if (list.size() > 1) { needSplitParam = new ArrayList<>(new HashSet<>(list)); } } int batchNum = getBatchNum(needSplitParam, splitGroupNum); if (batchNum == 1) { return pjp.proceed(); } CompletableFuture<?>[] futures = new CompletableFuture[batchNum]; ThreadPoolEnum threadPool = splitWorkAnnotation.setThreadPool(); if (threadPool == null) { return pjp.proceed(); }
try { for (int currentBatch = 0; currentBatch < batchNum; currentBatch++) { int finalNeedSplitParamIndex = needSplitParamIndex; int finalCurrentBatch = currentBatch; Object finalNeedSplitParam = needSplitParam; futures[currentBatch] = CompletableFuture.supplyAsync(() -> { Object[] dest = new Object[args.length]; System.arraycopy(args, 0, dest, 0, args.length); try { dest[finalNeedSplitParamIndex] = getPartParam(finalNeedSplitParam, splitGroupNum, finalCurrentBatch); return pjp.proceed(dest); } catch (Throwable e) { throw new RuntimeException(e); } }, threadPool.getThreadPoolExecutor()); } CompletableFuture<Void> all = CompletableFuture.allOf(futures); all.get(); Class<? extends HandleReturn> handleReturn = splitWorkAnnotation.handlerReturnClass();
List<Object> resultList = new ArrayList<>(futures.length); for (CompletableFuture<?> future : futures) { resultList.add(future.get()); } return handleReturn.getDeclaredMethods()[0].invoke(handleReturn.getDeclaredConstructor().newInstance(), resultList); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); } }
public Integer getBatchNum(Object needSplitParam1, Integer splitGroupNum) { if (needSplitParam1 instanceof Object[]) { Object[] splitParam = (Object[]) needSplitParam1; return splitParam.length % splitGroupNum == 0 ? splitParam.length / splitGroupNum : splitParam.length / splitGroupNum + 1; } else if (needSplitParam1 instanceof Collection) { Collection<?> splitParam = (Collection<?>) needSplitParam1; return splitParam.size() % splitGroupNum == 0 ? splitParam.size() / splitGroupNum : splitParam.size() / splitGroupNum + 1; } else { return 1; } }
public Object getPartParam(Object needSplitParam, Integer splitGroupNum, Integer batch) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { if (needSplitParam instanceof Object[]) { Object[] splitParam = (Object[]) needSplitParam; int end = Math.min((batch + 1) * splitGroupNum, splitParam.length); return Arrays.copyOfRange(splitParam, batch * splitGroupNum, end); } else if (needSplitParam instanceof List) { List<?> splitParam = (List<?>) needSplitParam; int end = Math.min((batch + 1) * splitGroupNum, splitParam.size()); return splitParam.subList(batch * splitGroupNum, end); } else if (needSplitParam instanceof Set) { List splitParam = new ArrayList<>((Set) needSplitParam); int end = Math.min((batch + 1) * splitGroupNum, splitParam.size()); Set<?> set = (Set<?>) needSplitParam.getClass().getDeclaredConstructor().newInstance(); set.addAll(splitParam.subList(batch * splitGroupNum, end)); return set; } else { return null; } } }
|