论坛首页 Java企业应用论坛

关于利用javassis获取方法的形参名

浏览 9140 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2014-06-11  

大家知道在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 为什么接口又不可以,或者有什么其他方式可以?

 

菜鸟提问,如有不当请包涵,谢谢

 

   发表时间:2014-06-12   最后修改:2014-06-12
想要获取到参数名有两种办法
1.在编译的时候加debug参数(eclipse编译的时候默认就加了),"对java方法,参数实际是按照局部变量来存储的,所以可以获取参数名称;但对于java接口中的方法声明,这种方法就无法获取参数名称"
2.通过一些maven插件(如下),在编译的时候修改字节码,将参数名字存储在类的成员变量里
<dependency>
			<groupId>com.thoughtworks.paranamer</groupId>
			<artifactId>paranamer</artifactId>
			<version>2.3</version>
</dependency>


引用:http://drizzlewalk.blog.51cto.com/2203401/1118792
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics