Java AOP JoinPoint不获取参数名称

时间:2014-08-10 07:23:13

标签: java spring spring-mvc spring-aop spring-aspects


我正在使用Java Spring Mvc和Spring AOP从用户那里查找参数名称。
我有一个控制器,它从用户获取参数并调用服务。
我有一个方面,在服务之前运行。
方面应检查username和apiKey参数是否存在。
这是我的代码:

控制器:

@RequestMapping(method = RequestMethod.POST, produces=MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody String getDomainWithFoundIn(@RequestParam (value="domain") String domain, @RequestParam (value="user") String user, @RequestParam (value="apiKey") String apiKey) throws JsonGenerationException, JsonMappingException, IOException {
    return domainService.getDomainDataWithFoundIn(domain, user, apiKey);
}

域服务接口:

public interface IDomainService {
    public String getDomainDataWithFoundIn(String domainStr, String user, String apiKey);
}

DomainService:

@Override
@ApiAuthentication
public String getDomainDataWithFoundIn(String domainStr, String user, String apiKey) {
//Do stuff here
}

我的AOP课程:

@Component
@Aspect
public class AuthAspect {
@Before("@annotation(apiAuthentication)") 
public void printIt (JoinPoint joinPoint, ApiAuthentication apiAuthentication) throws NoAuthenticationParametersException, UserWasNotFoundException {
        final MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        final String[] parameterNames = signature.getParameterNames();
        **//parameterNames is null here.**
}

在这种情况下,我希望在我的方面获得“domain”,“user”和“apiKey”参数名称。
知道我在这里缺少什么吗?
谢谢,

3 个答案:

答案 0 :(得分:6)

正如我在上面的评论中所说,根据代理类型,您可以或不可以访问参数名称。如果你的bean实现了接口,那么JDK代理将由spring创建,在这种代理中,MethodSignature.getParameterNames()为null。如果您的bean没有实现接口,则创建CGLIB代理,其中MethodSignature.getParameterNames()被填充。

如果可以,您可以通过删除bean接口切换到CGLIB代理bean,它应该可以工作。

我现在正在努力解决这个问题,我无法删除接口。我想出了不同的解决方案。在界面上,我可以通过一些自定义注释来标记我的参数:

interface MyInterface {
  void myMetod(@ParamName("foo") Object foo, @ParamName("bar") Object bar);
}

现在在AOP代理中我可以获得以下信息:

MethodSignature.getMethod().getParameterAnnotations()

答案 1 :(得分:1)

我只能使用Java 8在Eclipse中完成这项工作。方法如下:

  • 右键单击项目 - >属性 - > Java构建路径 - >库选项卡并确保您添加JDK 8而不是现在的(在我的情况下,我有JDK_1.7.0_51并将其替换为JDK_1.8.0_05)。应用更改。
  • 转到Java Compiler - >检查Enable project specific settings - >检查Use default compliance settings并将Compiler compliance level设置为1.8。 Generated .class files compatibilitySource compatibility也是如此。
  • Classfile Generation部分确保选中Store method parameter names选项(在我的测试中,我已选中Classfile Generation下的所有选项)。在我的情况下,Store method parameter names选项仅适用于合规级别1.8。点击Ok
  • 清理并重新编译您的项目。
  • 我也使用JDK 8在Tomcat 7上运行我的项目。无需在调试模式下运行它。

在STS 3.5.1(Eclipse Kepler SR2 4.3.2)中进行了测试。

答案 2 :(得分:1)

最简单的方法是在配置文件中设置proxyTargetClass,即

@EnableAspectJAutoProxy(proxyTargetClass = true)