ASM
Используя ASMifierClassVisitor
, вы можете точно увидеть, какой код нужно написать для генерации внутренних классов:
ASMifierClassVisitor.main(new String[] { PurchaseOrder.customer_Field.class
.getName() });
Остальное простоопределить, какие биты вам нужно параметризировать в коде вашего генератора.Пример вывода для PurchaseOrder$customer_Field
, который станет файлом inject/PurchaseOrder$customer_Field.class
:
public static byte[] dump () throws Exception {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(V1_6, ACC_SUPER, "inject/PurchaseOrder$customer_Field",
"Ljava/lang/Object;"+
"Linject/PropertyAccessor<Linject/PurchaseOrder;Linject/Customer;>;",
"java/lang/Object",
new String[] { "inject/PropertyAccessor" });
//etc
(я использовал «inject» в качестве пакета.)
Вы будететакже необходимо создать искусственные средства доступа с использованием классов посетителей ASM:
{
mv = cw.visitMethod(ACC_STATIC + ACC_SYNTHETIC, "access$0",
"(Linject/PurchaseOrder;Linject/Customer;)V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(PUTFIELD, "inject/PurchaseOrder",
"customer", "Linject/Customer;");
mv.visitInsn(RETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_STATIC + ACC_SYNTHETIC, "access$1",
"(Linject/PurchaseOrder;)Linject/Customer;", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, "inject/PurchaseOrder", "
customer", "Linject/Customer;");
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
См. этот проект для примера того, как внедрить методы.Благодаря этому я полностью избегаю затрат на рефлексию.
Поскольку все это будет сделано во время выполнения:
- , это предварительная стоимость этого анализа игенерация кода
- вам нужно как-то обнаружить и проанализировать эти сгенерированные типы