Мне нужно создать аспект, который должен после генерирования пользовательского исключения снова вызывать метод с теми же аргументами, где это исключение было брошено, но рекурсивный вызов метода должен быть не более 5 раз. Возможно ли это сделать?
Рекурсивный вызов Spring Aspect
Ответы (1)
Я использовал аннотацию, чтобы быть более беглым:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
/** Annotation for ascect using to define how many times try running annotated method */
public @interface TryMultiplyTimes {
/** define how many time try running method */
int times() default 0;
}
В методе, который вы хотите запустить несколько раз, получите аннотацию с объявлением, сколько раз вам нужно (в моем случае это класс DAO):
@Component
public class CustomerDAOImpl{
@TryMultiplyTimes(times=5)
public void addCustomerThrowException(String text) throws Exception {
System.out.println("addCustomerThrowException() is running with args: "+text);
throw new Exception("Generic Error");
}
И самая важная часть: аспект. Мой аспект основан на аннотации вокруг метода вызова. Аспект пытается вызвать метод, когда получает исключение, проверяет, может ли вызывать метод больше раз; если нет, то исключение. Ключ - это хэш-код класса и метода, чтобы различать вызов одного и того же метода разными объектами.
@Aspect
public class MultiTimesAspect {
@Around("@annotation(multiTimeAnnotation)")
public void aspectMultiTime(ProceedingJoinPoint joinPoint, TryMultiplyTimes multiTimeAnnotation)throws Throwable {
System.out.println("***********************************************");
System.out.println("before running method: "+ joinPoint.getSignature().getName());
try {
joinPoint.proceed(joinPoint.getArgs()); //running method with it's args
} catch (Throwable e) {
//if method throws exception:
int times = multiTimeAnnotation.times();//get how many times can trying
String key = createKey(joinPoint); //create key (class hashCode and method hashCode) for managing map
if (repeatsMap.get(key) == null) {
repeatsMap.put(key, 1); //if method called first time
}
int proceeded = repeatsMap.get(key);
if (proceeded < times) {
//if can try more times preincrement reapeats and recursively call aspect
repeatsMap.replace(key, ++proceeded);
aspectMultiTime(joinPoint, multiTimeAnnotation);
} else {
//if can't call method anymore, delete from map key and throws excetion
repeatsMap.remove(key);
throw e;
}
}
System.out.println("after running method: " + joinPoint.getSignature().getName());
System.out.println("***********************************************");
}
private String createKey(JoinPoint joinPoint) {
StringBuffer buffer = new StringBuffer();
buffer.append(joinPoint.getTarget().toString()).append(".")
.append(joinPoint.getThis().toString());
return buffer.toString();
}
}
И тестовый класс
public class Test {
public static void main(String... args){
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
"spring-aop.xml");
CustomerDAOImpl customer= (CustomerDAOImpl) ctx.getBean("customerBo");
try {
customer.addCustomerThrowException("**TEST**");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
person
Victor1125
schedule
14.12.2015
@Around
, который повторяется максимум 5 раз, вызывая рекомендуемый метод. - person Sotirios Delimanolis   schedule 17.04.2014