ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及 Java 字节码(指令)。ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。
缺点: ReflectAsm无法针对私有方法、私有属性
引入依赖:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>reflectasm</artifactId>
<version>1.11.0</version>
</dependency>
目标类:
@Data
public class Person {
public String userName;
public Integer age;
public Person(String userName, Integer age) {
this.userName = userName;
this.age = age;
}
public Person() {
}
public String select(String keyWord){
return "这个一个测试:"+keyWord;
}
}
测试类:
public class ReflectTest {
/**
* JDK反射调用方法
*
* <p>
* setAccessible(false);
* </p>
*
* @throws Exception
*/
@Test
public void testJdkReflectMethod() throws Exception {
Person person = new Person();
long start = System.currentTimeMillis();
Class<?> aClass = Person.class;
Method method = aClass.getDeclaredMethod("select", String.class);
for (int i = 0;i<10000;i++){
method.invoke(person, "hello word");
}
long end = System.currentTimeMillis();
System.out.println("JDK反射调用方法耗时"+(end - start));
}
/**
* JDK反射调用方法
*
* <p>
* setAccessible(true);
* </p>
*
* @throws Exception
*/
@Test
public void testJdkReflectMethod1() throws Exception {
Person person = new Person();
long start = System.currentTimeMillis();
Class<?> aClass = Person.class;
Method method = aClass.getDeclaredMethod("select", String.class);
method.setAccessible(true);
for (int i = 0;i<10000;i++){
method.invoke(person, "hello word");
}
long end = System.currentTimeMillis();
System.out.println("JDK反射调用方法耗时Accessible :"+(end - start));
}
/**
* ReflectAsm反射调用方法
*
* <p>
* 用名称定位反射方法
* </p>
*
* @throws Exception
*/
@Test
public void testReflectAsmMethodName() throws Exception {
Person person = new Person();
//生成字节码的方式创建PersonMethodAccess
MethodAccess methodAccess = MethodAccess.get(Person.class);
long start = System.currentTimeMillis();
for (int i = 0;i<10000;i++){
methodAccess.invoke(person, "select","hello word");
}
long end = System.currentTimeMillis();
System.out.println("ReflectAsm反射调用方法(用名称定位反射方法)耗时"+(end - start));
}
/**
* ReflectAsm反射调用方法
*
* <p>
* 用方法和字段的索引定位反射方法,性能高
* </p>
*
* @throws Exception
*/
@Test
public void testReflectAsmMethodIndex() throws Exception {
Person person = new Person();
//生成字节码的方式创建PersonMethodAccess
MethodAccess methodAccess = MethodAccess.get(Person.class);
int index = methodAccess.getIndex("select", String.class);
long start = System.currentTimeMillis();
for (int i = 0;i<10000;i++){
methodAccess.invoke(person, index,"select","hello word");
}
long end = System.currentTimeMillis();
System.out.println("ReflectAsm反射调用方法(用方法和字段的索引定位反射方法)耗时"+(end - start));
}
/**
* ReflectAsm反射:set/get字段值
*
*/
@Test
public static void testReflectAsmField(){
Person person = new Person();
FieldAccess fieldAccess = FieldAccess.get(Person.class);
fieldAccess.set(person,"userName","test");
String userName = (String) fieldAccess.get(person, "userName");
int index = fieldAccess.getIndex("userName");
String accessString = fieldAccess.getString(person, index);
System.out.println(userName+"<<<<<<<<<<<<<"+accessString);
}
/**
* ReflectAsm反射:构造方法
*
*/
@Test
public void testReflectAsmConstructor() {
ConstructorAccess<Person> constructorAccess = ConstructorAccess.get(Person.class);
Person person = constructorAccess.newInstance();
person.setAge(12);
System.out.println(person.toString());
}
}