внедряване на aspectj логване в таймера на Java

Имам метод, който хвърля IOException, който се извиква от java timer run(). Тъй като run() не връща никакви проверени изключения и аз използвам AspectJ за регистриране, как да регистрирам изключението в aspectj?

Това е моят код:

timer = new Timer(); `

    timer.scheduleAtFixedRate(new TimerTask() {

        public void run() {

            for (OidTypes oidType : typesList) {

                try {
                    valueIncrementOperation(oidType);//------this method throws exception
                } catch (IOException e) {

                    System.out.println("Error occured inside Timer : "
                            + e.getMessage());

                    timer.cancel();
                    timer = null;
                }

            }

` Засега съм принуден да използвам try/catch. Какви са моите възможности?


person yonikawa    schedule 13.11.2013    source източник
comment
опитайте да извикате e.getCause()   -  person Peter Quiring    schedule 14.11.2013
comment
@PeterQuiring: Опитвам се да се отърва от блока try/catch, така че откъде да го извикам, тъй като aspectj не може да прихване run().   -  person yonikawa    schedule 14.11.2013


Отговори (2)


Първо трябва да опаковате IOException в непроверено изключение, истинското изключение ще бъде причината за изключението, което улавяте в съвета.

Най-простият е да вземете RuntimeException.

public void doTimerJob() {
    final Timer timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            try {
                throw new IOException("file not found");
            } catch (IOException e) {
                timer.cancel();
                throw new RuntimeException(e);
            }
        }
    }, new Date(), 2000);
}

След това можете да опитате следното:

Създайте точково изрязване за TimerTask#run

pointcut timerTaskRun() : execution(public * java.util.TimerTask.run(..) );

и съвет за след хвърляне на RuntimeException

after() throwing(RuntimeExceptione) : timerTaskRun() {
    System.out.println("log and rethrow " + e.getCause().getMessage());
}

Това ще хвърли отново изключението, след като го регистрирате.

Ако искате да влезете и да преглътнете изключението, можете да напишете около съвет

Object around() : timerTaskRun() {
    Object o;
    try {
        o = proceed();   
    } catch(RuntimeException e) {
        System.out.println("log and swallow " + e.getCause().getMessage());
        o = null;
    }
    return o;
}

Обърнете внимание, че трябва да имате само един от съветите, after throwing или around, а не и двата.

Но може да не искате да съветвате всички TimerTask#run обаждания заедно с всички RuntimeExceptions. В този случай трябва да създадете собствени типове, които да използвате в точковото изрязване и съветите.

„Неотметнато“ IOException

public class IOExceptionUnchecked extends RuntimeException {
    private static final long serialVersionUID = 1L;
    public IOExceptionUnchecked(IOException e) {
        super(e);
    }
}

Персонализирана TimerTask

public class MyTimerTask extends TimerTask  {
    Timer owner = null; 
    public MyTimerTask(Timer timer) {this.owner = timer;}
    @Override
    public void run() {
        try {
            throw new IOException("file not found");
        } catch (IOException e) {
            owner.cancel();
            throw new IOExceptionUnchecked(e);
        }
    }
}

Точково изрязване

pointcut timerTaskRun() : execution(public * com.example.MyTimerTask.run(..) );

след хвърляне на съвет:

after() throwing(IOExceptionUnchecked e) : timerTaskRun() {
    System.out.println("log and rethrow " + e.getCause().getMessage());
}

Или около съвети

Object around() : timerTaskRun() {
    Object o;
    try {
        o = proceed();   
    } catch(IOExceptionUnchecked e) {
        System.out.println("log and swallow " + e.getCause().getMessage());
        o = null;
    }
    return o;
}
person A4L    schedule 14.11.2013
comment
благодаря ти много, брато.. оценявам времето и усилията, които вложи, за да публикуваш кода и да разгледаш всички подробности... определено ще се опитам да го внедря... благодаря отново... - person yonikawa; 14.11.2013
comment
@decentguy добре дошъл! Надяваме се, че ще ви помогне да намерите начин да решите проблема си! - person A4L; 14.11.2013

Не можете да се отървете от блока try/catch, защото IOException е проверено изключение, а TimerTask#run е декларирано, че не хвърля никакви проверени изключения. Също така имате допълнителна логика в catch блока за отмяна на таймера.

Най-близкото нещо, което можете, е да увиете IOException в RuntimeException и да го хвърлите отново.

   catch(IOException){
        timer.cancel();
        throw new RuntimeException(e);
    }

Дори ако направите това, изключението и проследяването на стека няма да бъдат регистрирани от AspectJ. За да направите това, трябва да използвате контейнер (като Spring), за да създадете екземпляра TimerTask и да го обвиете с прехващач на AspectJ.

person Changgeng    schedule 13.11.2013
comment
благодаря за коментара и използвам Spring MVC. Как да обвия екземпляра TimerTask с aspectj? - person yonikawa; 14.11.2013
comment
Има няколко стъпки: 1) преместете анонимния клас в клас от първо ниво. 2) управлява bean с spring, или чрез анотация, или го поставя в контекстния файл на spring, имайте предвид, че може да се наложи да използвате prototype обхват. 3) приложете свързана с aspectj анотация - person Changgeng; 14.11.2013