java中Objenesis库简单使用

前言

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-知乎

posted @ 2021-10-30 10:19  strongmore  阅读(1107)  评论(0编辑  收藏  举报