可以注释获取上下文对象吗?

时间:2013-06-05 02:47:06

标签: java annotations spring-aop

也许标题“可以注释获取上下文对象吗?”是不正确的,但我不知道如何给它一个正确和明确的。

我使用Spring AOP + Java Annotation来保存日志,这是我的代码:

CategoryAction.java:

@ServiceTracker(methodDesp="save category, category name:"+this.category.getName())
public String save() throws Exception
{
    this.categoryService.save(this.category);
    this.setJsonDataSimply(null);
    return "save";
}

TrackAdvice.java:

public Object trackAround(ProceedingJoinPoint point) throws Throwable
{
    String log = "success";
    ServiceTracker tracker = null;
    Method method = null;
    AbstractAction action = null;
    try
    {
        Object result = point.proceed();
        action = (AbstractAction) point.getTarget();
        MethodSignature signature = (MethodSignature) point.getSignature();
        method = signature.getMethod();
        tracker = method.getAnnotation(ServiceTracker.class);
        return result;
    }
    catch (Exception e)
    {
        log = e.getMessage();
        throw e;
    }
    finally
    {
        if (tracker != null)
        {
            String userId = (String) ActionContext.getContext().getSession().get(Constant.USERID);
            if (userId == null)
            {
                userId = "unknown";
            }
            TrackLog t = new TrackLog();
            t.setWhen(new Date());
            t.setUserId(userId);
            t.setResult(log);
            t.setMethodName(action.getClass().getCanonicalName() + "." + method.getName());
            t.setMethodDesp(tracker.methodDesp());
            this.trackService.save(t);
        }
    }
}

ServiceTracker是我自己的注释,在我的TrackAdvice类中,我得到当前的执行方法,如果方法有ServiceTracker注释,则保存methodDesp对数据库的注释。

现在的问题是注释中的methodDesp是动态的,我希望得到this对象并检索其category属性。

似乎Java Annotation不支持这一点,也许它支持但我不知道如何。

2 个答案:

答案 0 :(得分:2)

  

似乎Java Annotation不支持此

你是对的 - 在纯java中无法做到这一点。

原因是因为注释是静态元数据,它连接到并在编译时this定义开始只在运行时存在,而不是在编译时存在。)

换句话说,没有简单的方法可以使某些类动态的注释方法methodDesp,因为它的值必须在编译时静态解析。

然而,从技术上讲,有一种方法可以做你想要的事情。我所说的是使用javassist在运行时操作或创建类(以及应用于它们的注释)。但请注意,这是相当黑客的方式,我通常不建议去那里。

答案 1 :(得分:2)

您可以做的是在注释值中使用某种表达式语言,然后在您的建议代码中运行一些解释器。使用SPEL的一个示例可能如下所示:

@ServiceTracker(methodDesp="save category, category name: #{category.name}")

然后在您的建议代码中,您可以提取表达式标记,使用SpelExpression并将target引用作为根对象传递给它(您可能需要检查可用的内容) SPEL API中用于支持您的用例的框。