Простое (непроверенное, использование на свой страх и риск) решение, которое могло бы сработать, состояло бы в том, чтобы поддерживать счетчик для метода на поток:
private static final ConcurrentHashMap<String, ConcurrentHashMap<Long, AtomicInteger>>
COUNTERS = new ConcurrentHashMap<>();
public static int getInvocationId(String methodName, long threadId) {
return counter(methodName, threadId).getAndIncrement();
}
private static AtomicInteger counter(String methodName, long threadId) {
ConcurrentHashMap<Long, AtomicInteger> map = countersForMethodName(methodName);
AtomicInteger counter = map.get(threadId);
if (counter == null) {
AtomicInteger newCounter = new AtomicInteger();
counter = map.putIfAbsent(threadId, newCounter);
if (counter == null) {
return newCounter;
}
}
return counter;
}
private static ConcurrentHashMap<Long, AtomicInteger> countersForMethodName(
String methodName) {
ConcurrentHashMap<Long, AtomicInteger> map = COUNTERS.get(methodName);
if (map == null) {
ConcurrentHashMap<Long, AtomicInteger> newMap = new ConcurrentHashMap<>();
map = COUNTERS.putIfAbsent(methodName, newMap);
if (map == null) {
return newMap;
}
}
return map;
}
Тогда, по вашему совету, что-то вроде:
int invocationId = getInvocationId(thisJoinPoint.getSignature().getName(),
Thread.currentThread().getId());
// do what you want with invocationId
Обратите внимание, что это опирается на рекомендацию, выполняемую в том же потоке, что и целевой метод - к сожалению, я не настолько знаком с AspectJ, чтобы знать, будет ли это предположение всегда выполняться.
CAVEAT: Если ваша среда все время создает и истекает новые потоки, то вышеупомянутое дерево будет продолжать расти (по сути, утечка памяти). Если это проблема, то вам нужно будет вставить какой-то другой код, чтобы периодически перечислять все активные потоки и удалять устаревшие записи из дерева. В этом случае вы можете использовать идентификатор карты для каждого потока, а затем имя для метода, чтобы сделать сокращение более эффективным.