好的参考文章:
http://my.oschina.net/u/1166271/blog/163637
http://blog.csdn.net/conquer0715/article/details/42129327
http://www.oschina.net/question/2008762_167680
asm在解析文件的时候是按照特定顺序进行分析的,首先是visit方法,做类相关的解析,然后是注解,然后是属性,最后才是方法,属性是在所有方法分析前面进行,也就是只有当class文件中的所有属性都遍历完毕之后,才会去遍历方法:测试代码如下
package test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class FilterGetOrSetMethodUtil extends ClassVisitor {
public static final int ASM_API_VERSION = Opcodes.ASM5;
public List<String> nameList = new ArrayList<String>();
public List<String> methodList = new ArrayList<String>();
public FilterGetOrSetMethodUtil() {
super(ASM_API_VERSION);
}
public void visit(int version, int access, String name, String signature,
String superName, String[] interfaces) {
System.out.println(version+" "+access+" "+name+" "+signature+" "+superName);
}
//访问类注解
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
return super.visitAnnotation(desc, visible);
}
//访问类属性
public FieldVisitor visitField(int access, String name, String desc,
String sig, Object value) {
nameList.add(name);
System.out.println("nameList:"+nameList.toString());
return super.visitField(access, name, desc, sig, value);
}
//访问方法,获取到的方法暂未使用
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
System.out.println("hahah:"+nameList.toString());
if(!("<init>".equals(name)||"<clinit>".equals(name)))
methodList.add(name);
System.out.println("methodList:"+methodList.toString());
return super.visitMethod(access, name, desc, signature, exceptions);
}
//构造类内部属性相关的get和set方法,与methodName比较
private boolean methodType(String methodName) {
boolean isFlag = false;
for(String name:nameList) {
String getName = "get" + name.substring(0,1).toUpperCase()+name.substring(1);
String setName = "set"+ name.substring(0,1).toUpperCase()+name.substring(1);
if(getName.equals(methodName)) {
isFlag = true;
break;
} else if(setName.equals(methodName)) {
isFlag = true;
break;
}
}
return isFlag;
}
public static boolean isSetOrGetMethod(String className,String methodName) {
boolean isFlag = false;
try {
//读取class文件
ClassReader creader = new ClassReader(
ClassLoader.getSystemResourceAsStream(className + ".class"));
FilterGetOrSetMethodUtil visitor = new FilterGetOrSetMethodUtil();
creader.accept(visitor, 0);//执行
isFlag = visitor.methodType(methodName);
return isFlag;
} catch (Exception e) {
e.printStackTrace();
}
return isFlag;
}
public static void main(String[] args) throws Exception {
// TestBean t = new TestBean();
// ClassReader creader = new ClassReader(
// ClassLoader.getSystemResourceAsStream(
// t.getClass().getName().replace(".", "/")+".class"));
System.out.println(FilterGetOrSetMethodUtil.isSetOrGetMethod("test/TestBean","getId"));
}
}
package test;
import javax.annotation.Generated;
import javax.annotation.Resource;
@Resource
public class TestBean {
public void testhaha(){}
private int test22() {
return 2;
}
static {
// System.out.println("niaho");
}
@Generated("id")
private int id;
public int getId() {
return id;
}
@Resource
public void setId(int id) {
this.id = id;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void toString(String s) {
System.out.println("s");
}
}
1、反射获取类中的属性和方法,并判定方法是否是set或者get方法
package test.dao;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.apache.commons.lang.StringUtils;
public class FilterDtoUtil {
public static void main(String[] args) {
System.out.println(FilterDtoUtil.isDtoClass("com.lxp.test.UserDto"));
}
//通过属性进行判定,如果有任何一个没有对应属性的get或者set方法,那么就判定为非dto
public static boolean isDtoClass(String className) {
boolean hasGetMethod = true;
boolean hasSetMethod = true;
try {
Class clz = Class.forName(className);
//首先判定类是否有注解,如果有的话就不是dto类
Annotation[] as = clz.getAnnotations();
if(clz.getAnnotations().length!=0) {
return false;
}
//遍历得到所有的属性
Field[] fields = clz.getDeclaredFields();
for(Field f : fields) {
//属性是否有注解
if(f.getAnnotations().length!=0) {
return false;
}
String fieldName = f.getName();
//拼装get和set方法
String getMethod = "get"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
String setMethod = "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
if(clz.getDeclaredMethod(getMethod, null)==null) {
hasGetMethod = false;
break;
}
if(clz.getDeclaredMethod(setMethod, f.getType())==null) {
hasSetMethod = false;
break;
}
}
//查看方法是否有注解
Method[] mm = clz.getDeclaredMethods();
for(Method m : mm) {
if(m.getAnnotations().length!=0) {
return false;
}
}
} catch (NoSuchMethodException e) {
// e.printStackTrace();
System.out.println("抛异常了NoSuchMethodException:没有找到相关方法!");
return false;
} catch (Exception e) {
e.printStackTrace();
}
return hasGetMethod && hasSetMethod;
}
//该方法暂不适用,判定依据不是很合理,是直接判定这个方法是否是get还是set,多个方法判定不好组织
public static boolean isDtoClass2(String className) {
boolean isDtoClass = false;
boolean hasGetMethod = false;
boolean hasSetMethod = false;
if(StringUtils.containsIgnoreCase(className, "DTO")) isDtoClass = true;
try {
Class clz = Class.forName(className);
Method[] ms = clz.getDeclaredMethods();
for(Method m : ms) {
System.out.println("haha"+m.getName());
if(isGetMethod(m)) {
hasGetMethod = true;
continue;
}
if(isSetMethod(m)) {
hasSetMethod = true;
continue;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return isDtoClass && hasGetMethod && hasSetMethod;
}
//判定一个方法是不是get方法
private static boolean isGetMethod(Method m) {
if(!m.getName().startsWith("get")) return false;
if(m.getParameterTypes().length!=0) return false;
if(void.class.equals(m.getReturnType())) return false;
return true;
}
//判定一个方法是否是set方法
private static boolean isSetMethod(Method m) {
if(!m.getName().startsWith("set")) return false;
if(m.getParameterTypes().length!=1) return false;
return true;
}
}
2、根据
class
文件和方法名判定该方法是否是get或者set方法
package test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class FilterGetOrSetMethodUtil extends ClassVisitor {
public static final int ASM_API_VERSION = Opcodes.ASM5;
public List<String> nameList = new ArrayList<String>();
public List<String> methodList = new ArrayList<String>();
public FilterGetOrSetMethodUtil() {
super(ASM_API_VERSION);
}
//访问类注解
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
return super.visitAnnotation(desc, visible);
}
//访问类属性
public FieldVisitor visitField(int access, String name, String desc,
String sig, Object value) {
nameList.add(name);
return super.visitField(access, name, desc, sig, value);
}
//访问方法,获取到的方法暂未使用
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
if(!("<init>".equals(name)||"<clinit>".equals(name)))
methodList.add(name);
return super.visitMethod(access, name, desc, signature, exceptions);
}
//构造类内部属性相关的get和set方法,与methodName比较
private boolean methodType(String methodName) {
boolean isFlag = false;
for(String name:nameList) {
String getName = "get" + name.substring(0,1).toUpperCase()+name.substring(1);
String setName = "set"+ name.substring(0,1).toUpperCase()+name.substring(1);
if(getName.equals(methodName)) {
isFlag = true;
break;
} else if(setName.equals(methodName)) {
isFlag = true;
break;
}
}
return isFlag;
}
public static boolean isSetOrGetMethod(String className,String methodName) {
boolean isFlag = false;
try {
//读取class文件
ClassReader creader = new ClassReader(
ClassLoader.getSystemResourceAsStream(className + ".class"));
FilterGetOrSetMethodUtil visitor = new FilterGetOrSetMethodUtil();
creader.accept(visitor, 0);//执行
isFlag = visitor.methodType(methodName);
return isFlag;
} catch (Exception e) {
e.printStackTrace();
}
return isFlag;
}
public static void main(String[] args) throws Exception {
// TestBean t = new TestBean();
// ClassReader creader = new ClassReader(
// ClassLoader.getSystemResourceAsStream(
// t.getClass().getName().replace(".", "/")+".class"));
System.out.println(FilterGetOrSetMethodUtil.isSetOrGetMethod("test/TestBean","getId"));
}
}