大家知道在springMVC中有注解可以映射web参数,例如:
@Controller public class IndexController { @RequestMapping("/index/{username}") public String index(@PathVariable("username") String username) { System.out.print(username); return "index"; } }
@PathVariable 注解将web参数username映射到index方法的形参username上
我是在想, 若index方法的形参变量名与web参数名一致,也就是上面这种情况,都叫username, 那么我是不是可以省略这个@PathVariable注解呢
要实现这个功能,意味着必须使用某种方式,例如反射,可以得到给定class的方法的参数名,于是,就想着能实现这样一个方法:
String[] getMethodParameterNames(Method method){ // code... }
例如,将index这个方法传入后,可得到结果: ["username"]
这个方法能否实现呢, java自带的反射肯定没戏, 我找了一下,发现javassist貌似可以实现:
public interface MemberService { void login(String username, int sysid, String password); }
public class MemberServiceImpl implements MemberService{ @Override public void login(String username, int sysid, String password) { // Auto-generated method stub } }
@Test public void testImpl() throws Exception{ Class<MemberServiceImpl> clazz = MemberServiceImpl.class; Method method = clazz.getMethod("login", String.class, int.class, String.class); ClassPool pool = ClassPool.getDefault(); CtClass ctClass = pool.get(clazz.getName()); CtMethod ctMethod = ctClass.getDeclaredMethod(method.getName()); // 当前方法的信息 MethodInfo methodInfo = ctMethod.getMethodInfo(); CodeAttribute codeAttribute = methodInfo.getCodeAttribute(); LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag); String variableName; for (int i=0;i<method.getParameterTypes().length;i++){ variableName = attr.variableName(i + 1); System.out.println(variableName); } }
执行测试方法,控制台成功输出:
username
sysid
password
而当我将class由MemberServiceImpl.class改为MemberService.clss, 即由普通类改为接口后:
@Test public void testInterface() throws Exception{ Class<MemberService> clazz = MemberService.class; Method method = clazz.getMethod("login", String.class, int.class, String.class); ClassPool pool = ClassPool.getDefault(); CtClass ctClass = pool.get(clazz.getName()); CtMethod ctMethod = ctClass.getDeclaredMethod(method.getName()); // 当前方法的信息 MethodInfo methodInfo = ctMethod.getMethodInfo(); CodeAttribute codeAttribute = methodInfo.getCodeAttribute(); LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag); String variableName; for (int i=0;i<method.getParameterTypes().length;i++){ variableName = attr.variableName(i + 1); System.out.println(variableName); } }
报空指针错,attr为null
我疑惑的是
1 不是一旦经过编译后,方法的形参名信息就丢失了吗,javassist是如何做到能拿到形参变量名的
2 既然可以拿到形参名, 那么为什么spring或其他框架(如webservice)要用注解实现,而不直接依赖变量名注入? 若我想自己实现一个轻量前端框架,用依赖方法变量名的方式注入web参数,有什么问题吗?
3 为什么接口又不可以,或者有什么其他方式可以?
菜鸟提问,如有不当请包涵,谢谢