use of io.micronaut.context.AbstractConstructorInjectionPoint in project micronaut-core by micronaut-projects.
the class BeanDefinitionWriter method initInterceptedConstructorWriter.
private int initInterceptedConstructorWriter(GeneratorAdapter buildMethodVisitor, List<ParameterElement> parameters, @Nullable FactoryMethodDef factoryMethodDef) {
// write the constructor that is a subclass of AbstractConstructorInjectionPoint
InnerClassDef constructorInjectionPointInnerClass = newInnerClass(AbstractConstructorInjectionPoint.class);
final ClassWriter interceptedConstructorWriter = constructorInjectionPointInnerClass.innerClassWriter;
org.objectweb.asm.commons.Method constructorMethod = org.objectweb.asm.commons.Method.getMethod(CONSTRUCTOR_ABSTRACT_CONSTRUCTOR_IP);
GeneratorAdapter protectedConstructor;
final boolean hasFactoryMethod = factoryMethodDef != null;
final String interceptedConstructorDescriptor;
final Type factoryType = hasFactoryMethod ? factoryMethodDef.factoryType : null;
final String factoryFieldName = "$factory";
if (hasFactoryMethod) {
// for factory methods we have to store the factory instance in a field and modify the constructor pass the factory instance
newFinalField(interceptedConstructorWriter, factoryType, factoryFieldName);
interceptedConstructorDescriptor = getConstructorDescriptor(new Type[] { TYPE_BEAN_DEFINITION, factoryType });
protectedConstructor = new GeneratorAdapter(interceptedConstructorWriter.visitMethod(ACC_PROTECTED, CONSTRUCTOR_NAME, interceptedConstructorDescriptor, null, null), ACC_PROTECTED, CONSTRUCTOR_NAME, interceptedConstructorDescriptor);
} else {
interceptedConstructorDescriptor = constructorMethod.getDescriptor();
protectedConstructor = new GeneratorAdapter(interceptedConstructorWriter.visitMethod(ACC_PROTECTED, CONSTRUCTOR_NAME, interceptedConstructorDescriptor, null, null), ACC_PROTECTED, CONSTRUCTOR_NAME, interceptedConstructorDescriptor);
}
if (hasFactoryMethod) {
protectedConstructor.loadThis();
protectedConstructor.loadArg(1);
protectedConstructor.putField(constructorInjectionPointInnerClass.innerClassType, factoryFieldName, factoryType);
}
protectedConstructor.loadThis();
protectedConstructor.loadArg(0);
protectedConstructor.invokeConstructor(Type.getType(AbstractConstructorInjectionPoint.class), constructorMethod);
protectedConstructor.returnValue();
protectedConstructor.visitMaxs(1, 1);
protectedConstructor.visitEnd();
// now we need to implement the invoke method to execute the actual instantiation
final GeneratorAdapter invokeMethod = startPublicMethod(interceptedConstructorWriter, METHOD_INVOKE_CONSTRUCTOR);
if (hasFactoryMethod) {
invokeMethod.loadThis();
invokeMethod.getField(constructorInjectionPointInnerClass.innerClassType, factoryFieldName, factoryType);
pushCastToType(invokeMethod, factoryType);
} else {
invokeMethod.visitTypeInsn(NEW, beanType.getInternalName());
invokeMethod.visitInsn(DUP);
}
for (int i = 0; i < parameters.size(); i++) {
invokeMethod.loadArg(0);
invokeMethod.push(i);
invokeMethod.arrayLoad(TYPE_OBJECT);
pushCastToType(invokeMethod, parameters.get(i));
}
if (hasFactoryMethod) {
if (factoryMethodDef.factoryMethod instanceof MethodElement) {
invokeMethod.visitMethodInsn(INVOKEVIRTUAL, factoryType.getInternalName(), factoryMethodDef.factoryMethod.getName(), factoryMethodDef.methodDescriptor, false);
} else {
invokeMethod.getField(factoryType, factoryMethodDef.factoryMethod.getName(), beanType);
}
} else {
String constructorDescriptor = getConstructorDescriptor(parameters);
invokeMethod.visitMethodInsn(INVOKESPECIAL, beanType.getInternalName(), "<init>", constructorDescriptor, false);
}
invokeMethod.returnValue();
invokeMethod.visitMaxs(1, 1);
invokeMethod.visitEnd();
// instantiate a new instance and return
buildMethodVisitor.visitTypeInsn(NEW, constructorInjectionPointInnerClass.constructorInternalName);
buildMethodVisitor.visitInsn(DUP);
// pass outer class instance to constructor
buildMethodVisitor.loadThis();
if (hasFactoryMethod) {
buildMethodVisitor.loadLocal(factoryMethodDef.factoryVar);
pushCastToType(buildMethodVisitor, factoryType);
}
buildMethodVisitor.visitMethodInsn(INVOKESPECIAL, constructorInjectionPointInnerClass.constructorInternalName, "<init>", interceptedConstructorDescriptor, false);
final int constructorIndex = buildMethodVisitor.newLocal(Type.getType(AbstractConstructorInjectionPoint.class));
buildMethodVisitor.storeLocal(constructorIndex);
return constructorIndex;
}
Aggregations