使用AspectJ

时间:2016-05-08 21:00:34

标签: java aspectj

在我目前的项目中,我消耗了大量的JSON字符串。因此,我创建了一个实用程序方法来处理" org.json"引发的JSONExceptions。工具。这是我目前的做法:

我的json处理程序

public static <R> R handleJSONException(String operation, String params, String jsonString, FunctionWithJSONString<R> function) {

    try {
        return function.process(jsonString);
    } catch(JSONException jsonEx) {
        throw new myRunTimeException(
            StatusCode.ERROR_PARSING_JSON,
            "Error occurred while attempting to parse json: \"" + jsonString + "\"",
            "JSON parsing error occurred during operation, " + operation ", with params: " + params); 
    }
}

我的自定义功能界面:

@FunctionalInterface
public interface FunctionWithJSONString<R> {
    public R process(String jsonString) throws JSONException;
}

以下是其使用示例:

public Object getObjectFromJSONString(final String json) {

    String operation = "Get an Object from some source";
    String params = "";

    return handleJSONException(operation, params, json, (jsonString) -> {
        JSONObject body = new JSONObject(jsonString);
        return body.getObject("object");
    })
}

(当然这段代码非常简单。通常会将它分成子方法;&#34; handleJSONException&#34;在传递它之前对json进行一些验证,但这给了它的jist)

问题在于,我不喜欢每次处理JSON时都有这些lambdas,或者每次处理JSONExceptions时都必须有一个方法processAndHandleJSON,它只传递对sub方法processJSON的引用(尽管我我更喜欢这种方法,而不是我所见过的任何其他方法。

我想也许我可以使用一些面向方面的编程。所以,我想出了这个设计(不包括配置类):

用于表示连接点的注释:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface JSONHandler {
}

加入点使用的建议:

@Aspect
public class JSONExceptionAdvice {

    @Around(@annotation(JSONHandler))
    public Object wrapJSONHandlingMethod(ProceedingJoinPoint joinPoint) throws throwable {
        try {
            return joinPoint.proceed(joinPoint.getArgs);
        } catch (JSONException jsonEx) {
            //Some method that throws the "myRunTimeException" with necessary parameters
        }
            return null;
    }
}

以下是它的一个例子:

@JSONHandler
public Object getObjectFromJSON(final String json) {
    JSONObject body = new JSONObject(json);
    return body.getObject("object");
}

然而,这并没有编译。为了让它编译并让方面捕获错误,&#34; getObjectFromJSON&#34;方法需要&#34;抛出JSONException&#34;在签名中。这意味着我仍然需要在梯子上的某个地方尝试/捕捉。更糟糕的是,这将是一个空洞的尝试/捕获,看起来很难看,或者是一些不知道它被处理得更低,懒惰的人。

如果我的注释可以抑制&#34;未处理的JSONException&#34;我希望它编译器中的警告,但根据我的理解,这不是一件容易的事。我所想到的任何其他想法都会回到我以前的想法,但更加冗长,最重要。

有没有人对AspectJ如何以干净的方式实现预期目标有任何想法?目标是否清楚明确?任何人都可以推荐一种比其中任何一种更好的方法吗?

我已经查看了StackOverflow上的其他问题,例如Exception handling through spring AOP + Aspectj,但是他们使用空的try / catch,或者完全忽略未处理的异常问题。

P.S。虽然这是json处理特有的,但我想将其应用于其他一些常见错误。所以,虽然欢迎org.json的答案,但我很可能会接受最通用的答案。

1 个答案:

答案 0 :(得分:0)

不确定我是否正确理解您的要求,但是如果您不需要捕获已检查的org.json.JSONException - s(使其表现得像RuntimeException),那么你是什么需要是AspectJ declare soft语句。声明为soft会将未经检查org.json.JSONException的已检查org.aspectj.lang.SoftException换行。这仅适用于原生AspectJ语法,您必须切换到AspectJ编译器来编译项目(因此,您不会因为没有捕获已检查的异常而导致编译错误,或者未声明它们与{{一起传播) 1}}客户端方法中的关键字。)

throws

请注意,使用public aspect JSONExceptionAdvice { declare soft: org.json.JSONException: @annotation(JSONHandler); after() throwing(org.json.JSONException e): @annotation(JSONHandler) { System.out.println(e); } } 建议您不会压制after throwing,它仍会在堆栈中向上传播(尽管它会软化),所以它最适合记录目的。如果您需要取消异常或进行任何其他类型的补偿,则需要使用org.json.JSONException建议而不是around