Objenesis,另一种实例化对象的方式

简介

Objenesis是一个Java的库,主要用来创建特定的对象。

由于不是所有的类都有无参构造器又或者类构造器是private,在这样的情况下,如果我们还想实例化对象,class.newInstance是无法满足的。

使用

public class Test {
    private int i;

    public Test(int i){
        this.i = i;
    }

    public void show(){
        System.out.println("test..." + i);
    }

    public static void main(String[] args) {
        Objenesis objenesis = new ObjenesisStd(true);
        Test test = objenesis.newInstance(Test.class);
        test.show();
    }
}

使用非常简单,运行后可以看到控制台打印出test...0

实现

1. new ObjenesisStd

Objenesis由子类ObjenesisObjenesisStd实现,构造方法中使用了缓存并且创建了StdInstantiatorStrategy对象

public ObjenesisStd(boolean useCache) {
    super(new StdInstantiatorStrategy(), useCache);
}

ObjenesisBase初始化strategy,创建ConcurrentHashMap存放缓存对象

protected final InstantiatorStrategy strategy;
protected ConcurrentHashMap<String, ObjectInstantiator<?>> cache;

public ObjenesisBase(InstantiatorStrategy strategy, boolean useCache) {
    if (strategy == null) {
        throw new IllegalArgumentException("A strategy can't be null");
    } else {
        this.strategy = strategy;
        this.cache = useCache ? new ConcurrentHashMap() : null;
    }
}

2. objenesis.newInstance

先从缓存中查找类是否存在,如果存在直接返回instantiator对象,否则调用StdInstantiatorStrategy.newInstantiatorOf方法创建新的newInstantiator对象,并且将newInstantiator对象放到cache缓存中。

ConcurrentHashMap的putIfAbsent方法:
  • 如果是新的记录,那么会向map中添加该键值对,并返回null
  • 如果已经存在,那么不会覆盖已有的值,直接返回已经存在的值
public <T> T newInstance(Class<T> clazz) {
    return this.getInstantiatorOf(clazz).newInstance();
}

public <T> ObjectInstantiator<T> getInstantiatorOf(Class<T> clazz) {
    if (clazz.isPrimitive()) {
        throw new IllegalArgumentException("Primitive types can't be instantiated in Java");
    } else if (this.cache == null) {
        return this.strategy.newInstantiatorOf(clazz);
    } else {
        ObjectInstantiator<?> instantiator = (ObjectInstantiator)this.cache.get(clazz.getName());
        if (instantiator == null) {
            ObjectInstantiator<?> newInstantiator = this.strategy.newInstantiatorOf(clazz);
            instantiator = (ObjectInstantiator)this.cache.putIfAbsent(clazz.getName(), newInstantiator);
            if (instantiator == null) {
                instantiator = newInstantiator;
            }
        }

        return instantiator;
    }
}

3. this.strategy.newInstantiatorOf

当前JVM平台是Java HotSpot,进入else分支,创建SunReflectionFactoryInstantiator实例对象

else {
    return new SunReflectionFactoryInstantiator(type);
}

重点看下SunReflectionFactoryInstantiator的构造过程

public SunReflectionFactoryInstantiator(Class<T> type) {
    Constructor<Object> javaLangObjectConstructor = getJavaLangObjectConstructor();
    this.mungedConstructor = SunReflectionFactoryHelper.newConstructorForSerialization(type, javaLangObjectConstructor);
    this.mungedConstructor.setAccessible(true);
}

3.1 getJavaLangObjectConstructor返回Object类的构造器

private static Constructor<Object> getJavaLangObjectConstructor() {
    try {
        return Object.class.getConstructor((Class[])null);
    } catch (NoSuchMethodException var1) {
        throw new ObjenesisException(var1);
    }
}

3.2 newConstructorForSerialization创建新的构造器mungedConstructor

  • getReflectionFactoryClass通过Class.forName("sun.reflect.ReflectionFactory")获取ReflectionFactory Class
  • createReflectionFactory调用ReflectionFactory类的getReflectionFactory方法获取reflectionFactory实例
  • getNewConstructorForSerializationMethod获取ReflectionFactory类的newConstructorForSerialization Method
  • 执行getNewConstructorForSerializationMethod方法,传入reflectionFactory,Test.class和Object构造器。
public static <T> Constructor<T> newConstructorForSerialization(Class<T> type, Constructor<?> constructor) {
    Class<?> reflectionFactoryClass = getReflectionFactoryClass();
    Object reflectionFactory = createReflectionFactory(reflectionFactoryClass);
    Method newConstructorForSerializationMethod = getNewConstructorForSerializationMethod(reflectionFactoryClass);

    try {
        return (Constructor)newConstructorForSerializationMethod.invoke(reflectionFactory, type, constructor);
    } catch (IllegalArgumentException var6) {
        throw new ObjenesisException(var6);
    } catch (IllegalAccessException var7) {
        throw new ObjenesisException(var7);
    } catch (InvocationTargetException var8) {
        throw new ObjenesisException(var8);
    }
}
  • 调用ReflectionFactory.newConstructorForSerialization,由于var1 != var2,因此生成新的构造器
public Constructor<?> newConstructorForSerialization(Class<?> var1, Constructor<?> var2) {
    return var2.getDeclaringClass() == var1 ? var2 : this.generateConstructor(var1, var2);
}
该方法利用了asm字节码技术,将Test.class传入后返回 GeneratedSerializationConstructorAccessor1 对象,封装生成的新Constructor对象。

private final Constructor<?> generateConstructor(Class<?> var1, Constructor<?> var2) {
    SerializationConstructorAccessorImpl var3 = (new MethodAccessorGenerator()).generateSerializationConstructor(var1, var2.getParameterTypes(), var2.getExceptionTypes(), var2.getModifiers(), var2.getDeclaringClass());
    Constructor var4 = this.newConstructor(var2.getDeclaringClass(), var2.getParameterTypes(), var2.getExceptionTypes(), var2.getModifiers(), langReflectAccess().getConstructorSlot(var2), langReflectAccess().getConstructorSignature(var2), langReflectAccess().getConstructorAnnotations(var2), langReflectAccess().getConstructorParameterAnnotations(var2));
    this.setConstructorAccessor(var4, var3);
    var4.setAccessible(true);
    return var4;
}

3.3 设置mungedConstructor的access为true,SunReflectionFactoryInstantiator构造完成

4. this.getInstantiatorOf(clazz).newInstance

getInstantiatorOf完成之后,进入SunReflectionFactoryInstantiator.newInstance实例化对象过程。

public T newInstance() {
    try {
        return this.mungedConstructor.newInstance((Object[])null);
    } catch (Exception var2) {
        throw new ObjenesisException(var2);
    }
}

继续跟进Constructor类的newInstance方法。 最终调用ca.newInstance,ca也就是GeneratedSerializationConstructorAccessor1对象,实例化了Test对象。

public T newInstance(Object ... initargs)
    throws InstantiationException, IllegalAccessException,
           IllegalArgumentException, InvocationTargetException
{
    if (!override) {
        if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
            Class<?> caller = Reflection.getCallerClass();
            checkAccess(caller, clazz, null, modifiers);
        }
    }
    if ((clazz.getModifiers() & Modifier.ENUM) != 0)
        throw new IllegalArgumentException("Cannot reflectively create enum objects");
    ConstructorAccessor ca = constructorAccessor;   // read volatile
    if (ca == null) {
        ca = acquireConstructorAccessor();
    }
    @SuppressWarnings("unchecked")
    T inst = (T) ca.newInstance(initargs);
    return inst;
}

总结

综上步骤,完成一个对象的创建步骤如下

//创建Object构造器
Constructor<Object> objectConstructor = Object.class.getConstructor(null);

//获取ReflectionFactory类
Class<?> reflectionFactoryClass = Class.forName("sun.reflect.ReflectionFactory");
//实例化ReflectionFactory对象
Object reflectionFactory = reflectionFactoryClass.getDeclaredMethod("getReflectionFactory").invoke(null);
//调用newConstructorForSerialization,传入object构造器和Test类,创建新的构造器
Constructor<?> constructor = (Constructor<?>) reflectionFactoryClass
        .getDeclaredMethod("newConstructorForSerialization", Class.class, Constructor.class)
        .invoke(reflectionFactory, Test.class, objectConstructor);
//设置access为true
constructor.setAccessible(true);
//实例化Test对象
Test test = (Test) constructor.newInstance(null);
//调用方法
test.show();

猜你喜欢

转载自blog.csdn.net/ghaohao/article/details/80472500