问题
I'm using Java Spring Mvc and Spring AOP to find the parameter names from the user.
I have a controller which get parameters from user and call a service.
I have an aspect that running before the service.
The aspect should check if username and apiKey parameters are exist.
Here is my code :
Controller :
@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);
}
Domain Service Interface :
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
}
And my AOP class :
@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.**
}
In this case, I'd expect to get on my aspect the "domain", "user" and "apiKey" parameter names.
Any idea what am i missing here ?
Thanks,
Or.
回答1:
As I've said in above comment, depending on proxy type you can or can't have access to parameter names. If your bean implements interface, the JDK proxy will be created by spring, and in this kind of proxy MethodSignature.getParameterNames() is null. If your bean doesn't implement interface, CGLIB proxy is created, where MethodSignature.getParameterNames() is filled.
If you can, you may switch to CGLIB proxy bean by removing bean interfaces and it should work.
I'm struggling with the same now, and I can't remove interfaces. I figured out different solution for this. On the interface I can mark my parameters by some custom annot:
interface MyInterface {
void myMetod(@ParamName("foo") Object foo, @ParamName("bar") Object bar);
}
Now in AOP proxy I can get this information in:
MethodSignature.getMethod().getParameterAnnotations()
回答2:
I could make this work in Eclipse with Java 8 only . Here's how:
- Right Click on the project -> Properties -> Java Build Path -> Libraries tab and make sure you add there a JDK 8 instead of what you have now (in my case I had JDK_1.7.0_51 and replaced it with JDK_1.8.0_05). Apply changes.
- Go to Java Compiler -> Check
Enable project specific settings
-> CheckUse default compliance settings
and setCompiler compliance level
to 1.8. The same goes forGenerated .class files compatibility
andSource compatibility
. - At the
Classfile Generation
section make sure to checkStore method parameter names
option (in my tests, I had all the options underClassfile Generation
checked). TheStore method parameter names
option was available in my case only for a compliance level of 1.8. ClickOk
. - Clean and re-compile your project.
- I have, also, run my project on Tomcat 7 with JDK 8. No need to run it in Debug mode.
Tested this in STS 3.5.1 (Eclipse Kepler SR2 4.3.2).
回答3:
The simplest way is to set proxyTargetClass
in your config file, i.e.
@EnableAspectJAutoProxy(proxyTargetClass = true)
来源:https://stackoverflow.com/questions/25226441/java-aop-joinpoint-does-not-get-parameter-names