Рекурсивный вызов Spring Aspect

Мне нужно создать аспект, который должен после генерирования пользовательского исключения снова вызывать метод с теми же аргументами, где это исключение было брошено, но рекурсивный вызов метода должен быть не более 5 раз. Возможно ли это сделать?


person user3545768    schedule 17.04.2014    source источник
comment
Что вызывает исключение? Совет или рекомендованный метод? Просто сделайте совет @Around, который повторяется максимум 5 раз, вызывая рекомендуемый метод.   -  person Sotirios Delimanolis    schedule 17.04.2014


Ответы (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