2012-06-08 59 views
16

Tôi thấy rằng Guice và Spring sử dụng AOP Alliance dưới sự che chở cho các biện pháp can thiệp, và tôi đã cố gắng tìm cách làm sao để AOP Alliance chặn và xử lý một số ngoại lệ nhất định. viết cùng một mã lặp đi lặp lại bên trong mỗi khối catch.Xử lý ngoại lệ AOP

Nhưng sau khi xem lại, có vẻ như AOP Alliance không cung cấp bất kỳ cách nào để chặn chặn Throwable s theo cách mà trình xử lý/trình chặn có thể thực hiện một số thứ (ngoại trừ, v.v.) và sau đó xác định có hay không để tuyên truyền ngoại trừ thêm nữa hoặc chỉ phục hồi trở lại vào dòng tiếp theo sau dòng mà ném ngoại lệ:

HerpDerp hd = null; 

if(hd == null) 
    throw new RuntimeException("Herpyl derp!"); 

Manny.pacquiao(); 

tôi đang tìm kiếm một AOP cơ chế xử lý ngoại lệ đó sẽ đánh chặn các RuntimeException và sử dụng logic nghiệp vụ để quyết định có tiếp tục truyền hoặc khôi phục lại cuộc gọi Manny.pacquioa() hay không .

  • Nếu nó chỉ là không thể làm được điều này trong Java, xin vui lòng cho tôi biết
  • Bất kể có hay không nó có thể làm điều này trong Java, là có một cách để ngăn chặn ngoại lệ ném với AOP Alliance hoặc tôi có phải đi đâu đó không. Và nếu tôi phải đi đâu đó, ở đâu? AspectJ?

Cảm ơn!

Trả lời

30

Bạn có thể bắt ngoại lệ với Spring AOP, nhưng tôi không biết liệu điều đó có phù hợp với yêu cầu của bạn đối với một khung công tác Java thuần túy hay không.

Với mùa xuân, bạn có thể viết một đánh chặn AOP đơn giản như một cái gì đó như:

@Aspect 
public class ErrorInterceptor{ 
@AfterThrowing(pointcut = "execution(* com.mycompany.package..* (..))", throwing = "ex") 
public void errorInterceptor(WidgetException ex) { 
    if (logger.isDebugEnabled()) { 
     logger.debug("Error Message Interceptor started"); 
    } 

    // DO SOMETHING HERE WITH EX 
    logger.debug(ex.getCause().getMessage()); 


    if (logger.isDebugEnabled()) { 
     logger.debug("Error Message Interceptor finished."); 
    } 
} 
} 

nhưng không có cách nào để trở về phương pháp gọi điện thoại hoặc tiếp tục xử lý trên dòng tiếp theo. Tuy nhiên, nếu bạn xử lý ngoại lệ ở đây, nó sẽ không làm bong bóng chuỗi trừ khi bạn tự mình làm lại nó.

1

Để "bắt" ngoại lệ còn tự do với AspectJ, bạn có thể sử dụng các khía cạnh sau:

pointcut uncaughtExceptionScope() : 
    (execution(* com.mycompany.myrootpackage..Main.main(..)) 
    || execution(* java.util.concurrent.Callable+.call()) 
    || execution(* java.lang.Runnable+.run()) 
    )); 

after() throwing(Throwable t) : uncaughtExceptionScope() && !cflow(adviceexecution()) { 
    handleException(thisJoinPoint, t); 
} 

protected void handleException(JoinPoint jp, Throwable t) 
{ 
    // handle exception here 
} 

Tôi không nghĩ rằng nó có thể "quay trở lại" đến điểm thi.

+0

Cảm ơn @Wim - là AOP-based xử lý ngoại lệ như thế này là không thể với AOP Alliance? – IAmYourFaja

+0

Tôi không nghĩ vậy. Nếu bạn kiểm tra [tài liệu xuân] (http://static.springsource.org/spring/docs/3.1.1.RELEASE/spring-framework-reference/html/aop.html), nó sẽ hiển thị điều này: 'Tham gia điểm : một điểm trong khi thực hiện một chương trình, chẳng hạn như việc thực hiện một phương thức hoặc xử lý một ngoại lệ. Trong Spring AOP, một điểm nối luôn luôn đại diện cho một phương thức thực hiện.' –

+0

Có thể [ConstructorInterceptor] (http://aopalliance.sourceforge.net/doc/org/aopalliance/intercept/ConstructorInterceptor.html) bằng cách nào đó bị tấn công để chặn các ngoại lệ (khi chúng được xây dựng)? – IAmYourFaja

3

Có lý do khiến điều này không tồn tại. Nó sẽ yêu cầu viết lại cấu trúc khối của mã của bạn như thể bạn đã viết khối try/catch ở vị trí đầu tiên. Điều này, có vẻ như với tôi, có khả năng đóng tàn phá với phạm vi biến đổi và những thứ khác. Bạn đang yêu cầu AOP viết lại mã byte giống như mã sau đây, và đó là viết lại khá.

HerpDerp hd = null; 

try { 
    if(hd == null) 
     throw new RuntimeException("Herpyl derp!"); 
} catch(RuntimeException e) { 
    if (someConditionIsMet) { 
     throw e; 
    } 
} 

Manny.pacquiao(); 
1

@ 4herpsand7derpsago Nếu bạn đang cố gắng làm là để bắt ngoại lệ ném sử dụng AOP để thực hiện nhiệm vụ khác nhau để xử lý nó và sau đó trở lại vào mã nơi ngoại lệ ban đầu ném, tôi nghĩ rằng bạn bỏ lỡ hiểu khái niệm về AOP.

Như bạn chỉ ra trong mã của bạn

HerpDerp hd = null; 

if(hd == null) 
throw new RuntimeException("Herpyl derp!"); 

Manny.pacquiao(); 

Nếu bạn muốn AOP để bắt RuntimeException của bạn, thực hiện một số công cụ để xử lý nó và trở lại để Manny.pacquiao();, câu trả lời là bạn không thể. Lý do là vì khi RuntimeException bị ném và bị AOP chặn, ngăn xếp đã ở mã AOP của bạn. bạn không thể quay lại để thực thi Many.pacquiao();. Cách duy nhất nếu bạn muốn tiếp tục thực hiện Many.pacquiao(); là bằng cách sử dụng try-finally khối như sau

HerpDerp hd = null; 

try { 
    if(hd == null) 
     throw new RuntimeException("Herpyl derp!"); 
} finally { 
    Manny.pacquiao(); 
} 

Chỉ khi đó Many.pacquiao() của bạn sẽ được thực hiện, nhưng trước khi AOP của bạn bắt RuntimeException