Objenesis是一个小的java库,主要用来实例化类对象,java本身仅支持通过构造器实例化,实例化时必须使用合适的构造器,但有些情况下不能使用这种方式实例化:
一些常见的类库都要求类包含一个默认的无参构造器,而Objenesis可以绕过构造器来实例化对象。
定义一个用来实例化的类,不包含默认构造器
public class User { private String name; public User(String name) { System.out.println("User.Constructor"); } @Override public String toString() { return "User.toString()"; } }
使用Objenesis实例化对象
import org.objenesis.Objenesis; import org.objenesis.ObjenesisStd; import org.objenesis.instantiator.ObjectInstantiator; public class TestObjenesis { public static void main(String[] args) { //创建Objenesis,内部包含一个实例化策略对象StdInstantiatorStrategy Objenesis objenesis = new ObjenesisStd(); //获取对象实例化器 ObjectInstantiator objectInstantiator = objenesis.getInstantiatorOf(User.class); //实例化对象 System.out.println(objectInstantiator.newInstance()); } }
输出结果为
User.toString()
根据输出结果可以得知确实绕过了构造器。
默认使用的实例化策略对象类型为StdInstantiatorStrategy,会根据JVM供应商的不同,JVM版本的不同来选择不同的实例化器。
如我们使用的HotSpot虚拟机,就会使用SunReflectionFactoryInstantiator实例化器,底层使用ReflectionFactory类来实例化对象,
关于ReflectionFactory的使用,可以查看 java魔法类之ReflectionFactory介绍 这篇博客。
如果上述条件都不满足就会使用UnsafeFactoryInstantiator实例化器,内部使用Unsafe类的allocateInstance()方法实例化对象,
关于Unsafe,可以查看 java魔法类之Unsafe介绍 这篇博客。
Spring中集成了Objenesis库,在使用Cglib创建动态代理对象时就使用到了Objenesis。
Spring中定义的SpringObjenesis和Objenesis中的标准实现ObjenesisStd相比,在使用缓存时,使用Class对象代替Class名称作为缓存的key。
objenesis官网
objenesis-知乎