spring获得了一个模板/通用java。朗,反思一下。组织中的方法对象。aspectj。lang.ProceedingJoinPoint
如果AspectJ的工作方式与EJB拦截器的工作方式相同,那么这个问题就不存在了
考虑基本场景EJB拦截器方式:
@AroundInvoke
public Object log(final InvocationContext ctx) throws Exception {
// do stuff before
final Object result = ctx.proceed();
// do stuff after
return result;
}
现在我需要被拦截的方法对象。在这里,我可以简单地做到:
Method method = ctx.getMethod();
就这样,在这之后,我将检查截取方法的注释
现在我正在使用部署到servlet容器(Tomcat)的应用程序,因此没有EJB。其中的AOP是使用Spring+AspectJ实现的
around方法如下所示:
@Around("execution(* foo.bar.domain.integration.database.dao..*(..))")
public Object log(final ProceedingJoinPoint pjp) throws Throwable {
// do stuff before
final Object result = pjp.proceed();
// do stuff after
return result;
}
在这里,我不能再这样做了:
Method method = pjp.getMethod(); // no such method exists
取而代之的是,我被迫自己使用反射获取方法对象,如下所示:
final String methodName = pjp.getSignature().getName();
final Object[] arguments = pjp.getArgs();
final Class[] argumentTypes = getArgumentTypes(arguments);
final Method method = pjp.getTarget().getClass().getMethod(methodName, argumentTypes);
在您想要掌握模板方法之前,它一直有效:
@Transactional
public <T extends Identifiable> T save(T t) {
if (null == t.getId()) {
create(t);
return t;
}
return update(t);
}
假设您按如下方式调用此方法:
Person person = new Person("Oleg");
personService.save(person);
您将收到:
Caused by: java.lang.NoSuchMethodException: foo.bar.domain.integration.database.dao.EntityService.save(foo.bar.domain.entity.Person)
这是由:
pjp.getTarget().getClass().getMethod()
问题是运行时不存在泛型,实际的方法签名是:
public Identifiable save(Identifiable t) {}
最终类[]argumentTypes将包含一个元素,其类型将为Person。所以这个电话:
pjp.getTarget().getClass().getMethod(methodName, argumentTypes);
将查找方法:
save(Person p)
而且找不到
所以问题是:如何获得java的模板方法对象的实例,该对象表示被截取的确切方法
我想其中一种方法就是用蛮力的方式: 获取参数超类/接口,并尝试使用这些类型获取方法,直到不再获得NoSuchMethodException,但这显然很难看。有没有一个正常的清洁方式可以做到这一点
# 1 楼答案
这一点并不明显,这要归咎于API
另见Spring AOP: how to get the annotations of the adviced method。我自己还没有测试过。那里的工作人员说,这为他解决了这个问题。对于另一种用途,需要额外的
@Around(annotation...)
注释。(例如,尝试将目标设置为仅METHOD
,并查看其行为)