czwartek, 3 grudnia 2009

Zmiękczanie wyjatków za pomocą AspectJ

Kolejną ciekawą możliwością jaką daje AspectJ jest automatyczna zamiana twardych (checked) wyjątków na miękkie (unchecked) - rozszerzających klasę RuntimeException.

Czemu ma służyć taki manewr? Oczywiście wygodzie programisty. ;) Czasem zdarza się, że pomiędzy miejscem powstania wyjątku, a miejscem jego obsługi jest po drodze wywoływanych wiele metod. Teraz jeśli rzucanym wyjątkiem jest wyjątek twardy to każda metoda po drodze musi zadeklarować ze może ewentualnie taki wyjątek rzucić.


package wyjatki;

public class Wyjatki {
static void test() throws NoSuchMethodException{
Wyjatki.class.getMethod("abc", String.class);
}
static void test2() throws NoSuchMethodException{
test();
}
public static void main(String[] args) {
try {
test2();
} catch (NoSuchMethodException e) {
//obsluga wyjatku
e.printStackTrace();
}
}
}


Jeśli pisanie deklaracji throws jest dla nas uciążliwe możemy obejść problem opakowywując twardy wyjątek w jego miękki odpowiednik.


package wyjatki;

public class Wyjatki {
static void test(){
try{
Wyjatki.class.getMethod("abc", String.class);
}catch(NoSuchMethodException e){
throw new RuntimeException(e);
}
}
static void test2(){
test();
}
public static void main(String[] args) {
try {
test2();
} catch (RuntimeException e) {
Throwable e2 = e.getCause();
//obsluga wyjatku
e2.printStackTrace();
}
}
}


Kod w działaniu zachowuje się tak samo, ale metody test oraz test2 nie muszą deklarować NoSuchMethodException. W każdym razie programista musi ręcznie opakować wyjątek. I tutaj na scenę wkracza AspectJ. Posiada on deklarację declare soft, która odpowiada za opakowanie twardego wyjątku jego miękkim odpowiednikiem. Dla naszego przykładu wygląda ona następująco:


package wyjatki;

public aspect WyjatkiAspect {
declare soft : NoSuchMethodException : execution(void wyjatki.Wyjatki.test());
}


Natomiast klasa Wyjatki prezentuje się następująco:


package wyjatki;

public class Wyjatki {
static void test(){
Wyjatki.class.getMethod("abc", String.class);
}
static void test2(){
test();
}
public static void main(String[] args) {
try {
test2();
} catch (RuntimeException e) {
Throwable e2 = e.getCause();
//obsluga wyjatku
e2.printStackTrace();
}
}
}


Jak widać nie dość, że pozbyliśmy się deklaracji throws to jeszcze wyeliminowaliśmy opakowywanie NoSuchMethodException w metodzie test.

Na koniec dosyć ważna uwaga: twarde wyjątki po istnieją, aby były jawnie obsługiwane, dlatego ten mechanizm nie służy temu aby opakować wyjątek i o nim zapomnieć. Trzeba pamietać, aby go właściwie obsłużyć.

Brak komentarzy:

Prześlij komentarz