RetryableAspect { @Around("@annotation(retryableAnnotation)") public Object call(final ProceedingJoinPoint pjp, Retryable retryableAnnotation) throws Throwable { final int maxTries = retryableAnnotation.maxTries(); final int retryDelayMillies = retryableAnnotation.retryDelayMillis(); final Class<? extends Throwable>[] retryOn = retryableAnnotation.retryOn(); final boolean doubleDelay = retryableAnnotation.doubleDelay(); final boolean throwCauseException = retryableAnnotation.throwCauseException(); if (logger.isDebugEnabled()) { logger.debug("Have @Retryable method wrapping call on method {} of target object {}", new Object[] { pjp.getSignature().getName(), pjp.getTarget() }); } ServiceRetrier serviceRetrier = new ServiceRetrier(retryDelayMillies, maxTries, doubleDelay, throwCauseException, retryOn); return serviceRetrier.invoke( new Callable<Object>() { public Object call() throws Exception { try { return pjp.proceed(); } catch (Exception e) { throw e; } catch (Error e) { throw e; } catch (Throwable t) { throw new RuntimeException(t); } } } ); } RetryableAspect(); @Around("@annotation(retryableAnnotation)") Object call(final ProceedingJoinPoint pjp, Retryable retryableAnnotation);  }
@Test public void testCall() throws Throwable { ProceedingJoinPoint mockPjp = createPjpMock(mockSignature); expect(mockPjp.proceed()).andReturn(null).times(1); replay(mockPjp); aspect.call(mockPjp, mockAnnotation); verify(mockPjp); verify(mockAnnotation); verify(mockSignature); }