最近接触了下javassist,试着进行字节码操纵,javassist的上手还是比较简单,官方文档说的很详细,而且例子也给的蛮多。
传送门:Javassist官方文档地址

下面是自己写的一个方法,其中生成了一个经典的Spring的controller类。具体写法如下,代码已经贴上了注释。

public void makeclass(String className,String methodName, CONSTANTS.INVOKETYPE invoketype,String interfaceCode) throws NotFoundException, CannotCompileException, IOException {
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.makeClass(className);
ClassFile ccFile = clazz.getClassFile();
ConstPool constpool = ccFile.getConstPool();

CtClass executor = pool.get("com.javassist.test.Executor");
CtClass requst = pool.get("javax.servlet.http.HttpServletRequest");
CtClass response = pool.get("javax.servlet.http.HttpServletResponse");

String fieldName = invoketype.getValue());
// 增加字段
CtField field = new CtField(executor,fieldName,clazz);
field.setModifiers(Modifier.PUBLIC);
FieldInfo fieldInfo = field.getFieldInfo();

// 属性附上注解
AnnotationsAttribute fieldAttr = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
Annotation autowired = new Annotation("org.springframework.beans.factory.annotation.Autowired",constpool);
fieldAttr.addAnnotation(autowired);
fieldInfo.addAttribute(fieldAttr);
clazz.addField(field);

// 增加方法,javassist可以直接将字符串set到方法体中,所以使用时非常方便
CtMethod method = new CtMethod(new CtClassType(CtClass.javaLangObject,pool),methodName,new CtClass[]{requst,response},clazz);
method.setModifiers(java.lang.reflect.Modifier.PUBLIC);
StringBuffer methodBody = new StringBuffer();
methodBody.append("{return "+fieldName+".execute(\""+interfaceCode+"\",(com.javassist.test.RequestVo)$1.getAttribute(\"request\"));}");
method.setBody(methodBody.toString());



// 类附上注解
AnnotationsAttribute classAttr = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
Annotation controller = new Annotation("org.springframework.stereotype.Controller",constpool);
Annotation requestMapping = new Annotation("org.springframework.web.bind.annotation.RequestMapping.RequestMapping",constpool);
String visitPath = "/api/department";
requestMapping.addMemberValue("value",new StringMemberValue(visitPath,constpool));
classAttr.addAnnotation(controller);
classAttr.addAnnotation(requestMapping);
ccFile.addAttribute(classAttr);

//方法附上注解
AnnotationsAttribute methodAttr = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
//Annotation annotation3 = new Annotation("org.springframework.web.bind.annotation.RequestMapping.RequestMapping",constpool);
requestMapping.addMemberValue("value",new StringMemberValue("/register",constpool));

Annotation responseBody = new Annotation("org.springframework.web.bind.annotation.RequestMapping.ResponseBody",constpool);
methodAttr.addAnnotation(requestMapping);
methodAttr.addAnnotation(responseBody);
MethodInfo info = method.getMethodInfo();
info.addAttribute(methodAttr);
clazz.addMethod(method);
clazz.writeFile();

}

需要注意的是,
1,运行在web容器或者Jboss下可能会出现找不到类,很有可能是类搜索路径的问题,可以通过增加搜索路径在试着解决问题,pool.insertClassPath(new ClassClassPath(this.getClass()));。
2,运行在web容器或者Jboss下可能会出现类加载器问题,报ClassCastException,可以不使用默认的类加载器,也可以自定义类加载器进行加载。

更多相关文章

  1. Java注解处理器(编译时注解)
  2. 关于JAVA类加载大家发表一下见解吧
  3. Javascript实现页面加载完成后自动刷新一遍清除缓存文件
  4. Javascript 同步异步加载详解 (十足的好文章!!强烈推荐)
  5. java远程类加载与轻客户端
  6. java动态加载jar文件
  7. 企业分布式微服务云SpringCloud SpringBoot mybatis (十四)Spring

随机推荐

  1. 那些为学校刷屏的人,刷的是什么?|无用但有
  2. 写给毕业后的自己!
  3. Kubernetes中的亲和性与反亲和性
  4. C++ 模板沉思录(上)
  5. Python 为什么推荐蛇形命名法?
  6. Python 为什么会有个奇怪的“...”对象?
  7. 最近学到的几个Excel可视化骚操作,必须分
  8. Python爬虫自动化,帮小姐姐解放双手
  9. 同学,你这简历上没项目啊!
  10. 详解 Python 的二元算术运算,为什么说减法